Spring学习第二周-揭开Spring中的Bean的面纱

Bean的配置

Spring容器支持XML和Properties两种格式的配置文件,在实际开发中,最常使用的就是XML格式的配置方式。这种配置方式通过XML文件来注册并管理Bean之间的依赖关系。在Spring中,XML配置文件的根元素是, 中包含了多个子元素,每一个子元素定义了一个Bean,并描述了该Bean如何被装配到Spring容器中。元素中同样包含了多个属性以及子元素,在配置文件中,通常一个普通的Bean只需要定义id(或name)和class两个属性即可。如果在Bean中未指定id和name,则Spring会将class值当作id使用。

Bean的实例化

构造器实例化

构造器实例化是指Spring容器通过Bean对应类中默认的无参构造方法来实例化Bean。
样例核心代码

//类
package com.itheima.instance.constructor
public class Bean1 {
    
    
}
//XML文件
<bean id="bean1" class="com.itheima.instance.constructor.Bean1" />

静态工厂方式实例化

使用静态工厂是实例化Bean的另一种方式。该方式要求开发者创建一个静态工厂的方法来创建Bean的实例,其Bean配置中的class属性所指定的不再是Bean实例的实现类,而是静态工厂类,同时还需要使用factory-method属性来指定所创建的静态工厂方法。下面通过一个案例来演示如何使用静态工厂方式实例化Bean。
样例核心代码

//类
package com.itheima.instance.constructor
public class Bean2 {
    
    
}
//静态工厂类
package com.itheima.instance.static_factory
public class MyBean2Factory{
    
    
//静态方法
public static Bean2 createBean(){
    
    
 return new Bean2();
}
}
//XML文件
<bean id="bean2" class="com.itheima.instance.static_factory.MyBean2Factory" factory-method="createBean" />

实例工厂方式实例化

此种方式的工厂类中,不再使用静态方法创建Bean实例,而是采用直接创建Bean实例的方式。同时,在配置文件中,需要实例化的Bean也不是通过class属性直接指向的实例化类,而是通过factory-bean属性指向配置的实例工厂,然后使用factory-method属性确定使用工厂中的哪个方法。

//类
package com.itheima.instance.constructor
public class Bean3 {
    
    
}
//实例工厂类
package com.itheima.instance.static_factory
public class MyBean3Factory{
    
    
//创建类实例的方法
public static Bean3 createBean(){
    
    
 return new Bean3();
}
}
//XML文件
<!--配置工厂-->
<bean id="bean2" class="com.itheima.instance.static_factory.MyBean3Factory" factory-method="createBean" />
<!--使用factory-bean属性指向配置的实例工厂-->
<!--使用factory-method属性确定使用工厂中的哪一个方法-->
<bean id="bean3" factory-bean="myBean3Factory" factory-method="createBean" />

Bean的作用域

通过Spring容器创建一个Bean的实例时,不仅可以完成Bean的实例化,还可以为Bean指定特定的作用域。

作用域的种类

singleton作用域

singleton是Spring容器默认的作用域,当Bean的作用域为singleton时,Spring容器就只会存在一个共享的Bean实例,并且所有对Bean的请求,只要id与该Bean的id属性相匹配,就会返回同一个Bean实例。singleton作用域对于无会话状态的Bean(如Dao组件、Service组件)来说,是最理想的选择。在Spring配置文件中,Bean的作用域是通过元素的scope属性来指定的,该属性值可以设置为singleton、prototype、request、session、globalSession、application和websocket七个值。要将作用域定义成singleton,只需将scope的属性值设置为singleton即可。

prototype作用域

需要保持会话状态的Bean(如Struts2的Action类)应该使用prototype作用域。在使用prototype作用域时,Spring容器会为每个对该Bean的请求都创建一个新的实例。要将Bean定义为prototype作用域,只需在配置文件中将元素的scope属性值设置为prototype即可。

Bean的生命周期

Spring容器可以管理singleton作用域的Bean的生命周期,在此作用域下,Spring能够精确地知道该Bean何时被创建,何时初始化完成以及何时被销毁。对于prototype作用域的Bean,Spring只负责创建,当容器创建了Bean实例后,Bean的实例就交给客户端代码来管理,Spring容器将不再跟踪其生命周期。每次客户端请求prototype作用域的Bean时,Spring容器都会创建一个新的实例,并且不会管那些被配置成prototype作用域的Bean的生命周期。了解Bean的生命周期的意义就在于,**可以在某个Bean生命周期的某些指定时刻完成一些相关操作。这种时刻可能有很多,但在一般情况下,常会在Bean的postinitiation(初始化后)和predestruction(销毁前)执行一些相关操作。**在Spring中,Bean生命周期的执行是一个很复杂的过程,读者可以利用Spring提供的方法来定制Bean的创建过程。当一个Bean被加载到Spring容器时,它就具有了生命,而Spring容器在保证一个Bean能够使用之前,会做很多工作
Bean的生命周期的整个执行过程描述如下。
(1)根据配置情况调用Bean构造方法或工厂方法实例化Bean。
(2)利用依赖注入完成Bean中所有属性值的配置注入。
(3)如果Bean实现了BeanNameAware接口,则Spring调用Bean的setBeanName()方法传入当前Bean的id值。
(4)如果Bean实现了BeanFactoryAware接口,则Spring调用setBeanFactory()方法传入当前工厂实例的引用。
(5)如果Bean实现了ApplicationContextAware接口,则Spring调用setApplicationContext()方法传入当前ApplicationContext实例的引用。(6)如果BeanPostProcessor和Bean关联,则Spring将调用该接口的预初始化方法postProcessBeforeInitialzation()对Bean进行加工操作,这个非常重要,Spring的AOP就是用它实现的。
(7)如果Bean实现了InitializingBean接口,则Spring将调用afterPropertiesSet()方法。
(8)如果在配置文件中通过init-method属性指定了初始化方法,则调用该初始化方法。
(9)如果有BeanPostProcessor和Bean关联,则Spring将调用该接口的初始化方法post ProcessAfterInitialization()。此时,Bean已经可以被应用系统使用了。
(10)如果在 中指定了该Bean的作用范围为scope=“singleton”,则将该Bean放入Spring IoC的缓存池中,将触发Spring对该Bean的生命周期管理;如果在中指定了该Bean的作用范围为scope=“prototype”,则将该Bean交给调用者,调用者管理该Bean的生命周期,Spring不再管理该Bean。
(11)如果Bean实现了DisposableBean接口,则Spring会调用destory()方法将Spring中的Bean销毁;如果在配置文件中通过destory-method属性指定了Bean的销毁方法,则Spring将调用该方法进行销毁。
Spring为Bean提供了细致全面的生命周期过程,通过实现特定的接口或通过的属性设置,都可以对Bean的生命周期过程产生影响。我们可以随意地配置的属性,但是在这里建议不要过多地使用Bean实现接口,因为这样会使代码和Spring聚合比较紧密。

Bean的装配方式

Bean的装配可以理解为依赖关系注入,Bean的装配方式即Bean依赖注入的方式。Spring容器支持多种形式的Bean的装配方式,如基于XML的装配、基于注解(Annotation)的装配和自动装配等(其中最常用的是基于注解的装配)。

基于XML的装配

Spring提供了两种基于XML的装配方式:设值注入(SetterInjection)和构造注入(Constructor Injection)。下面就讲解下如何在XML配置文件中使用这两种注入方式来实现基于XML的装配。在Spring实例化Bean的过程中,Spring首先会调用Bean的默认构造方法来实例化Bean对象,然后通过反射的方式调用setter方法来注入属性值。因此,设值注入要求一个Bean必须满足以下两点要求。· Bean类必须提供一个默认的无参构造方法。Bean类必须为需要注入的属性提供对应的setter方法。使用设值注入时,在Spring配置文件中,需要使用元素的子元素来为每个属性注入值;而使用构造注入时,在配置文件里,需要使用元素的子元素来定义构造方法的参数,可以使用其value属性(或子元素)来设置该参数的值。

基于Annotation的装配

在Spring中,尽管使用XML配置文件可以实现Bean的装配工作,但如果应用中有很多Bean时,会**导致XML配置文件过于臃肿,**给后续的维护和升级工作带来一定的困难。为此,Spring提供了对Annotation(注解)技术的全面支持。Spring中定义了一系列的注解,常用的注解如下所示。
@Component:可以使用此注解描述Spring中的Bean,但它是一个泛化的概念,仅仅表示一个组件(Bean),并且可以作用在任何层次。使用时只需将该注解标注在相应类上即可。
@Repository:用于将数据访问层(DAO层)的类标识为Spring中的Bean,其功能与@Component相同。
@Service:通常作用在业务层(Service层),用于将业务层的类标识为Spring中的Bean,其功能与@Component相同。
@Controller:通常作用在控制层(如Spring MVC的Controller),用于将控制层的类标识为Spring中的Bean,其功能与@Component相同。
@Autowired:用于对Bean的属性变量、属性的setter方法及构造方法进行标注,配合对应的注解处理器完成Bean的自动配置工作。默认按照Bean的类型进行装配。
@Resource:其作用与Autowired一样。其区别在于@Autowired默认按照Bean类型装配,而@Resource默认按照Bean实例名称进行装配。@Resource中有两个重要属性:name和type。Spring将name属性解析为Bean实例名称,type属性解析为Bean实例类型。如果指定name属性,则按实例名称进行装配;如果指定type属性,则按Bean类型进行装配;如果都不指定,则先按Bean实例名称装配,如果不能匹配,再按照Bean类型进行装配;如果都无法匹配,则抛出NoSuchBeanDefinitionException异常。
@Qualifier:与@Autowired注解配合使用,会将默认的按Bean类型装配修改为按Bean的实例名称装配,Bean的实例名称由@Qualifier注解的参数指定。
在上面几个注解中,虽然@Repository、@Service与@Controller功能与@Component注解的功能相同,但为了使标注类本身用途更加清晰,建议在实际开发中使用@Repository、@Service与@Controller分别对实现类进行标注。

猜你喜欢

转载自blog.csdn.net/qq_43515378/article/details/107585812