其他分享
首页 > 其他分享> > 《精通Spring4.x企业应用开发实战》第五章

《精通Spring4.x企业应用开发实战》第五章

作者:互联网

  第五章主要讲几种装配Bean的方法,其中xml方法是比较基础的方法,除此之外Java类和Groovy也可以装配,但是感觉SpringBoot中这两种方法好像被弃用了,SpringBoot中注解的方法用的比较多,专门为这一个小节做一些笔记吧。

  Spring 提供了一个context命名空间,它提供了通过扫描类包以应用注解定义Bean的方式,如代码所示。

  

  在①处声明context命名空间,在②处即可通过context命名空间的component-scan的base-package属性指定一个需要扫描的基类包,Spring容器将会扫描这个基类包里的所有类,并从类的注解信息中获取Bean的定义信息。

  如果仅希望扫描特定的类而非基包下的所有类,那么可以使用resource-pattern属性过滤出特定的类,如下:

  

 

  

  <context:include-filter>表示要包含的目标类,而<context:exclude-filter>表示要排除的目标类。一个<context:component-scan>下可以拥有若干个<context:exclude-filter>和<context: include-filter>元素。这两个过滤元素均支持多种类型的过滤表达式。说明如下:

  

  <context:component-scan>拥有一个容易被忽视的use-default-filters属性,其默认值为true,表示默认会对标注@Component、@Controller、@Service及@Reposity 的 Bean进行扫描。

  

 

  Spring通过@Autowired注解实现Bean的依赖注入。来看一个LogonService的例子,如代码所示:

  

  在①处使用@Service将LogonService标注为一个 Bean,在②处通过@Autowired注入LogDao 及 UserDao的 Bean。@Autowired 默认按类型(byType)匹配的方式在容器中查找匹配的 Bean,当有且仅有一个匹配的 Bean时,Spring将其注入@Autowired标注的变量中。

  如果容器中没有一个和标注变量类型匹配的 Bean,那么Spring 容器启动时将报NoSuchBeanDefinitionException异常。如果希望Spring即使找不到匹配的Bean完成注入也不要抛出异常,那么可以使用@Autowired(required=false)进行标注。

  

  如果容器中有一个以上匹配的 Bean时,则可以通过@Qualifier注解限定Bean 的名称,如代码所示。

  

  

  @Autowired可以对类成员变量及方法的入参进行标注,下面在类的方法上使用@Autowired注解,如代码所示。

  

 

  如果一个方法拥有多个入参,则在默认情况下,Spring将自动选择匹配入参类型的Bean进行注入。Spring 允许对方法入参标注@Qualifier 以指定注入 Bean的名称,如下:

  

 

  虽然Spring 支持在属性和方法上标注自动注入注解@Autowired,但在实际项目开发中建议采用在方法上标注@Autowired注解,因为这样更加“面向对象”,也方便单元测试的编写。如果将注解标注在私有属性上,则在单元测试时就很难用编程的办法设置属性值。

  Spring 4.0支持延迟依赖注入,即在 Spring容器启动的时候,对于在 Bean 上标注@Lazy 及@Autowired注解的属性,不会立即注入属性值,而是延迟到调用此属性的时候才会注入属性值,如代码所示。

  通过注解配置的 Bean和通过<bean>配置的 Bean一样,默认的作用范围都是singleton。Spring为注解配置提供了一个@Scope注解,可以通过它显式指定Bean的作目范围,如代码清单5-29所示。

  

  

 

 

5.8.1singleton作用域

  单例模式是重要的设计模式之一。在传统的应用开发中,需要手工为每个单实例类编写特定代码,在这种情况下,类的业务逻辑代码和模式代码紧密耦合在一起。Spring以容器的方式提供天然的单例模式功能,任何POJO无须编写特殊的代码,仅通过配置就可以享用单例模式的“大餐”。

  一般情况下,无状态或者状态不可变的类适合使用单例模式,不过Spring对此实现了超越。在传统开发中,由于DAO类持有Connection这个非线程安全的变量,因此往往未采用单例模式。而在 Spring环境下,对于所有的DAO类都可以采用单例模式,因为Spring利用AOP和LocalThread 功能,对非线程安全的变量(或称状态)进行了特殊处理,使这些非线程安全的类变成了线程安全的类(将在第7章介绍这一功能的内部机理)。

  因为Spring 的这一超越,所以在实际应用中,大部分Bean都能以单实例的方式运行,这也是为什么Spring将 Bean的默认作用域定为singleton的原因。singleton的 Bean在同一Spring loC容器中只有一个实例,请看下面的例子:

  

  ①处的car Bean声明为singleton(因为默认是singleton,所以无须显式指定),在容器中有3个其他的Bean引用了car Bean,如②、③、④所示。在容器内部,boss1、boss2和 boss3的car属性都指向同一个Bean,如图5-3所示。

  

   不但在配置文件中通过配置注入的 car引用相同的 car Bean,任何通过容器的getBean("car")方法返回的实例也指向同一个 Bean。在默认情况下,Spring的ApplicationContext容器在启动时,自动实例化所有singleton的Bean并缓存于容器中。虽然启动时会花费一些时间,但它带来两个好处:首先,对Bean提前进行实例化操作会及早发现一些潜在的配置问题;其次,Bean以缓存的方式保存,当运行时用到该Bean 时就无须再实例化了,提高了运行的效率。如果用户不希望在容器启动时提前实例化singleton的 Bean,则可以通过 lazy-init属性进行控制。

  

  lazy-init="true"的 Bean在某些情况下依然会提前实例化,如果该 Bean被其他需要提前实例化的 Bean所引用,那么Spring将忽略延迟实例化的设置。

 

5.8.2prototype 作用域 

  采用scope="prototype"指定非单例作用域的 Bean,请看下面的配置:

  

 

  通过以上配置,boss1、boss2、boss3所引用的都是一个新的car实例,每次通过容器的getBean("car")方法返回的也是一个新的car实例,如图所示。

  

  在默认情况下,Spring容器在启动时不实例化 prototype的 Bean。此外,Spring 容器将prototype的 Bean交给调用者后,就不再管理它的生命周期。

 

 

  

  

 

 

 

 

  

 

 

  

  

 

 

  

 

   

 

  

 

  

  

 

  

 

标签:容器,实例,Autowired,Spring,企业应用,Bean,第五章,注解,Spring4
来源: https://www.cnblogs.com/hellostranger/p/13981173.html