前叙:下图为spring创建加载对象的方式,值得注意的是会根据应用不同采用不同的加载方式。
学习注解的技巧:找xml中标签(属性)和注解的一一对应关系即可。
BeanFactory是Spring框架中IoC容器的顶层接口,它只是用来定义一些基础功能,定义一些基础规范,而ApplicationContext是它的一个子接口,所以ApplicationContext是具备BeanFactory提供的全部功能的。
通常,也成BeanFactory为SpringIoC的基础容器,ApplicationContext是容器的高级接口,比BeanFactory要拥有更多的功能,比如国际化支持和资源访问(xml,java配置类)等等。
第一种:JavaSE应用
必须引入jar:Spring IoC容器功能的jar:spring-context
不推荐使用FileSystemXmlApplicationContext的方式是因为:文件绝对路径,代码迁移的话这块很麻烦;
第一种:JavaWeb应用:监听器方式
必须引入jar:Spring Web功能的jar:spring-web
使用:WebApplicationContext
注意:
1)实际企业开发中,纯xml模式使用已经很少了
2)引入注解功能,不需要引入额外的jar
3)xml+注解结合,xml文件依然存在,所以SpringIOC容器的启动仍然从加载xml开始
一般Jdbc这种公共资源利用xml方式,具体实现类用注解方式
改造xml+注解模式,将xml中遗留的内容全部以注解的形式迁移出去,最终删除xml文件,从java的配置类启动。
对应注解
Bean对象的延迟加载(延迟创建)
ApplicationContext容器的默认行为是在启动服务器时将所有singleton bean提前进行实例化,提前实例化意味着作为初始化过程的一部分,ApplicationContext实例会创建并配置所有的singleton bean。(通常情况下这是件好事,因为这样在配置中的任何错误就会即刻被发现(否则的话可能要花几个小时甚至几天)。)
比如:
该bean默认的设置为: lazy-init="false" />
lazy-init="false",立退加载, 表示spring启动时,立刻进行实例化。(lazy-init 设置只对scop属性为singleton的bean起作用)
如果不想让singleton bean在ApplicationContext实例初始化时被提前实例化,可以将对象设置为延迟实例化。
lazy-init="true" />
设置为lazy-init="true"的bean将不会ApplicationContext启动时提前被实例化,而是在第一次向容器通过getBean索取bean时实例化的。
如果一个设置了立即加载的bean1,引入了一个延迟加载的bean2,那么在bean1被实例化的时候,bean2也会被实例化不会进行延迟实例化。
延迟加载应用场景
(1)开启延迟加载一定程度提高容器启动和运转性能;
(2)对应不常使用的Bean设置延迟加载,这样偶尔使用的时候在加载,不必要从一开始该bean就占用资源;
BeanFactory接口是容器的顶级接口,定义了容器的一些基础行为,在BeanFactory中可以创建和管理Spring容器中的Bean,它对于Bean的创建有一个统一的流程。具体使用它下面的子接口类型,比如ApplicationContext;
FactoryBean是一个工厂Bean,可以生成某一类型Bean实例,它最大的一个作用是:可以让我们自定义Bean的创建过程。
Spring中的Bean有两种:一种是普通Bean;一种是工厂Bean(FactoryBean),FactoryBean可以生产某一个类型的Bean实例,也就是说我们可以借助于它自定义Bean的创建过程;
Bean创建的三种方式:静态方法和实例化方法,利用工长bean的方式创建;
FactoryBean 接口定义如下:
// 可以让我们自定义Bean的创建过程(完成复杂bean的定义) public interface FactoryBean{ @Nullable // 返回FactoryBean创建的Bean实例,如果isSingleton返回true,则该实例会放到Spring容器的单例缓冲池中的Map。 T getObject() throws Exception; @Nullable // 返回FactoryBean创建的Bean类型 Class> getObjectType(); // 返回作用域是否是单例 default boolean isSingleton() { return true; } }
利用FactoryBean实现一个工长Bean:
/** * @description: 自定义FactoryBean实现 * @author: mj **/ @Component public class OrderFactoryBean implements FactoryBean { // 自定义bean的创建过程 @Override public Object getObject() throws Exception { System.out.println("-----调用OrderFactoryBean.getObject----"); // 1、直接new IOrderService orderService = new OrderServiceImpl(); return orderService; // 2、通过动态代理,无需实现类,如 Mybatis的xxxMapper接口 // OrderMapper bean = (OrderMapper) Proxy.newProxyInstance(OrderFactoryBean.class.getClassLoader(), new Class[]{OrderMapper.class}, new InvocationHandler() { // @Override // public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // // todo // System.out.println(method.getName()); // return null; // } // }); // return bean; } // 返回bean的class类型 @Override public Class> getObjectType() { return IOrderService.class; } // 是否单例,默认单例 @Override public boolean isSingleton() { return true; } }
Spring提供了两种后处理bean的扩展接口,分别为BeanPostProcessor和BeanFactoryPostProcessor,两者在使用上是有所区别的。一个是针对工长bean的后置处理器,一个是针对普通bean处理的;
工厂初始化(BeanFactory) --> Bean对象
在BeanFactory初始化之后可以使用BeanFactoryPostProcessor进行后置处理做一下事情;
在Bean对象实例化(并不是Bean的整个生命周期完成)之后可以使用BeanPostProcessor进行后置处理做一些事情;
注意:对象不一定是springbean,而springbean一定是个对象
BeanPostProcessor是针对Bean级别的处理,可以针对某个具体的Bean。
public interface BeanPostProcessor { @Nullable default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { reutrn bean; } }
该接口提供了两个方法,分别在Bean的初始化方法前和初始化方法后执行,具体这个初始化方法指的是什么方法,类似我们再定义bean时,定义了init-method所指定的方法。
定义一个类实现了BeanPostProcessor,默认是会对整个Spring容器中所有的bean进行处理。如果要对具体的某个bean处理,可以通过方法参数判断,两个类型参数分别为Object和String,第一个参数是每个bean的实例,第二个参数是每个bean的name或者id属性的值。所有可以通过第二个参数,来判断将要处理的具体的bean。
注意:处理是发生在Spring容器的实例化和依赖注入之后。
BeanFactory级别的处理,是针对整个Bean的工厂进行处理,典型应用:ProperyPlaceholderConfigurer
@FunctionalInterface public interface BeanFactoryPostProcessor { void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException; }
此接口只提供一个方法,方法参数为ConfigurableListableBeanFactory,该参数类型定义了一些方法:
其中有个方法名为getBeanDefinition的方法,我们可以根据此方法,找到我们定义bean的BeanDefinition对象。然后我们可以对定义个属性进行修改。
BeanDefinition对象:该对象很重要,我们在XML中定义的bean标签,Spring解析bean标签成为一个javaBean,这个javaBean就是BeanDefinition对象。
注意:调用BeanFactoryPostProcessor方法时,这时候bean还没有实例化,此时bean刚被解析成BeanDefinition对象。
BeanFactoryPostPostProcessor典型应用:
源码里面的PropertyPlaceholderConfigurer 替换属性分割符。 加载资源文件并且替换${}占位符的功能实现。
下面是源码:PropertyResourceConfigurer里面的核心方法:
读源码:
IoC容器是Spring的核心模块,是抽象了对象关系,依赖关系管理的架构解决方案,Spring提供了很多的容器,其中BeanFactory是顶层容器(根容器),不能被实例化(顶级接口),它定义了所有Ioc容器必须遵从的一套原则,具体的容器实现可以增加额外的功能,比如我们常用的ApplicationContext,其下更具体的实现如ClassPathXmlApplicationContext包含了解析xml等一系列的内容,AnnotationConfigApplicationContext则是包含了注解解析等一系列的内容。Spring IoC容器继承体系非常聪明,需要使用哪个层次用哪个层次即可,不必使用功能大而全的。
// spring ioc 容器源码缝隙基础案例 @Test public void testIoc() { // ApplicationContext是容器的高级接口,BeanFactory(顶级容器/根容器,规范了/定义了容器的基础行为) // Spring应用上下文,官方称之为IoC容器(错误的认识:容器就是map而已,准确来说,map是ioc容器的一个成员, // 叫做单例池,singletonObjects,容器是一组组件和过程的集合,包括BeanFactory,单例池,BeanPostProcessor等以及之间的协作流程) ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml); UserBean userBean = applicationContext.getBean(UserBean.class); }
BeanFactory顶级接口方法如下:
BeanFactory容器继承体系:
通过其接⼝设计,我们可以看到我们⼀贯使⽤的 ApplicationContext 除了继承 BeanFactory 的⼦接⼝, 还继承了ResourceLoader 、 MessageSource 等接⼝,因此其提供的功能也就更丰富了。
思路:创建⼀个类LagouBean,让其实现⼏个特殊的接⼝,并分别在接⼝实现的构造器、接⼝⽅法中断点,观察线程调⽤栈,分析出 Bean 对象创建和管理关键点的触发时机。
代码实现:
LagouBean类 package com.learn.science.ioc; import org.springframework.beans.factory.InitializingBean; /** * @author MJ * @date 2021/5/6 */ public class LagouBean implements InitializingBean { /** * 构造函数 */ public LagouBean() { System.out.println("LagouBean 构造器..."); } /** * InitializingBean 接⼝实现 */ public void afterPropertiesSet() throws Exception { System.out.println("LagouBean afterPropertiesSet..."); } } BeanPostProcessor 接⼝实现类 package com.learn.science.ioc; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; /** * @author MJ * @date 2021/5/6 */ public class MyBeanPostProcessor implements BeanPostProcessor { public MyBeanPostProcessor() { System.out.println("BeanPostProcessor 实现类构造函数..."); } @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if ("lagouBean".equals(beanName)) { System.out.println("BeanPostProcessor 实现类 postProcessBeforeInitialization ⽅法被调⽤中......"); } return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if ("lagouBean".equals(beanName)) { System.out.println("BeanPostProcessor 实现类 postProcessAfterInitialization ⽅法被调⽤中......"); } return bean; } } BeanFactoryPostProcessor 接⼝实现类 package com.learn.science.ioc; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; /** * @author MJ * @date 2021/5/6 */ public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { public MyBeanFactoryPostProcessor() { System.out.println("BeanFactoryPostProcessor的实现类构造函数..."); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { System.out.println("BeanFactoryPostProcessor的实现⽅法调⽤中......"); } } IoC 容器源码分析⽤例 package com.learn.science.ioc; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * Ioc 容器源码分析基础案例 * @author MJ * @date 2021/5/6 */ public class TestIoC { @Test public void testIoC() { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); LagouBean lagouBean = applicationContext.getBean(LagouBean.class); System.out.println(lagouBean); } } applicationContext.xml
( 1 )分析 Bean 的创建是在容器初始化时还是在 getBean 时
根据断点调试,我们发现,在未设置延迟加载的前提下, Bean 的创建是在容器初始化过程中完成的。
( 2 )分析构造函数调⽤情况
通过如上观察,我们发现构造函数的调⽤时机在 AbstractApplicationContext 类 refresh ⽅法的fifinishBeanFactoryInitialization(beanFactory)处 ;
( 3 )分析 InitializingBean 之 afterPropertiesSet 初始化⽅法调⽤情况
观察调⽤栈
通过如上观察,我们发现 InitializingBean 中 afterPropertiesSet ⽅法的调⽤时机也是在 AbstractApplicationContext类 refresh ⽅法的 fifinishBeanFactoryInitialization(beanFactory);
( 4 )分析 BeanFactoryPostProcessor 初始化和调⽤情况
分别在构造函数、 postProcessBeanFactory ⽅法处打断点,观察调⽤栈,发现 BeanFactoryPostProcessor 初始化 在 AbstractApplicationContext 类 refresh ⽅法的invokeBeanFactoryPostProcessors(beanFactory);
postProcessBeanFactory 调⽤ 在 AbstractApplicationContext 类 refresh ⽅法的
invokeBeanFactoryPostProcessors(beanFactory);
( 5 )分析 BeanPostProcessor 初始化和调⽤情况
分别在构造函数、 postProcessBeanFactory ⽅法处打断点,观察调⽤栈,发现 BeanPostProcessor 初始化 在 AbstractApplicationContext 类 refresh ⽅法的 registerBeanPostProcessors(beanFactory);
postProcessBeforeInitialization 调⽤ 在 AbstractApplicationContext 类 refresh ⽅法的 fifinishBeanFactoryInitialization(beanFactory);
postProcessAfterInitialization 调⽤ 在 AbstractApplicationContext 类 refresh ⽅法的
fifinishBeanFactoryInitialization(beanFactory);
( 6 )总结
根据上⾯的调试分析,我们发现 Bean 对象创建的⼏个关键时机点代码层级的调⽤都在AbstractApplicationContext 类 的 refresh ⽅法中,可⻅这个⽅法对于 Spring IoC 容器初始化来说相当
关键,汇总如下:
断点bebug看调用栈得到:
由上分析可知, Spring IoC 容器初始化的关键环节就在 AbstractApplicationContext#refresh() ⽅法中 ,我们查看 refresh ⽅法来俯瞰容器创建的主体流程,主体流程下的具体⼦流程我们后⾯再来讨论。
// class AbstractApplicationContext @Override public void refresh() throws BeansException, IllegalStateException { // 对象锁加锁 synchronized (this.startupShutdownMonitor) { // 第⼀步:刷新前的预处理 prepareRefresh(); /* 第⼆步: 获取BeanFactory;默认实现是DefaultListableBeanFactory 加载BeanDefition 并注册到 BeanDefitionRegistry */ // BeanFactory对象的创建流程 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 第三步:BeanFactory的预准备⼯作(BeanFactory进⾏⼀些设置,⽐如context的类加载器等) prepareBeanFactory(beanFactory); try { // 第四步:BeanFactory准备⼯作完成后进⾏的后置处理⼯作 postProcessBeanFactory(beanFactory); // 第五步:实例化并调⽤实现了BeanFactoryPostProcessor接⼝的Bean invokeBeanFactoryPostProcessors(beanFactory); // 第六步:注册BeanPostProcessor(Bean的后置处理器),在创建bean的前后等执⾏ registerBeanPostProcessors(beanFactory); // 第七步:初始化MessageSource组件(做国际化功能;消息绑定,消息解析); initMessageSource(); // 第⼋步:初始化事件派发器 initApplicationEventMulticaster(); // 第九步:⼦类重写这个⽅法,在容器刷新的时候可以⾃定义逻辑 onRefresh(); // 第⼗步:注册应⽤的监听器。就是注册实现了ApplicationListener接⼝的监听器bean registerListeners(); /* 第⼗⼀步: 初始化所有剩下的⾮懒加载的单例bean 初始化创建⾮懒加载⽅式的单例Bean实例(未设置属性) 填充属性 初始化⽅法调⽤(⽐如调⽤afterPropertiesSet⽅法、init-method⽅法) 调⽤BeanPostProcessor(后置处理器)对实例bean进⾏后置处 */ finishBeanFactoryInitialization(beanFactory); /* 第⼗⼆步: 完成context的刷新。主要是调⽤LifecycleProcessor的onRefresh()⽅法,并且发布事件 (ContextRefreshedEvent) */ finishRefresh(); } catch (BeansException ex) { .. } } }
// BeanFactory对象的创建流程
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
时序图如下:
( 1 )该⼦流程涉及到如下⼏个关键:
( 2 )过程的类调用过程分析
Step 1 : ⼦流程⼊⼝在 AbstractRefreshableApplicationContext#refreshBeanFactory ⽅法
Step 2 : 依次调⽤多个类的 loadBeanDefifinitions ⽅法
( 3 )时序图
创建 Bean 实例,此时尚未设置属性
普通 Bean 的初始化是在容器启动初始化阶段执⾏的,⽽被 lazy-init=true 修饰的 bean 则是在从容器⾥第⼀次进⾏context.getBean() 时进⾏触发。 Spring 启动的时候会把所有 bean 信息 ( 包括 XML 和注解 ) 解 析转化成Spring 能够识别的 BeanDefifinition 并存到 Hashmap ⾥供下⾯的初始化时⽤,然后对每个 BeanDefifinition 进⾏处理,如果是懒加载的则在容器初始化阶段不处理,其他的则在容器初始化阶段进⾏初始化并依赖注⼊
public void preInstantiateSingletons() throws BeansException { // 所有beanDefinition集合 ListbeanNames = new ArrayList (this.beanDefinitionNames); // 触发所有⾮懒加载单例bean的初始化 for (String beanName : beanNames) { // 获取bean 定义 RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); // 判断是否是懒加载单例bean,如果是单例的并且不是懒加载的则在容器创建时初始化 if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { // 判断是否是 FactoryBean if (isFactoryBean(beanName)) { final FactoryBean> factory = (FactoryBean>) getBean(FACTORY_BEAN_PREFIX + beanName); boolean isEagerInit; if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { isEagerInit = AccessController.doPrivileged(new PrivilegedAction () { @Override public Boolean run() { return ((SmartFactoryBean>) factory).isEagerInit(); } }, getAccessControlContext()); } } else { /* 如果是普通bean则进⾏初始化并依赖注⼊,此 getBean(beanName)接下来触发的逻辑 和 懒加载时 context.getBean("beanName") 所触发的逻辑是⼀样的 */ getBean(beanName); } } } }
总结
循环依赖其实就是循环引⽤,也就是两个或者两个以上的 Bean 互相持有对⽅,最终形成闭环。⽐如 A 依赖于B , B 依赖于 C , C ⼜依赖于 A 。
注意,这⾥不是函数的循环调⽤,是对象的相互依赖关系。循环调⽤其实就是⼀个死循环,除⾮有终结条件。
Spring 中循环依赖场景有:
其中,构造器的循环依赖问题⽆法解决,只能拋出 BeanCurrentlyInCreationException 异常,在解决属性循环依赖时,spring 采⽤的是提前暴露对象的⽅法。
对于原型bean的初始化过程中不论是通过构造器参数循环依赖还是通过setXxx⽅法产⽣循环依赖,Spring都 会直接报错处理。
AbstractBeanFactory.doGetBean()⽅法:
if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } protected boolean isPrototypeCurrentlyInCreation(String beanName) { Object curVal = this.prototypesCurrentlyInCreation.get(); return (curVal != null && (curVal.equals(beanName) || (curVal instanceof Set && ((Set>)curVal).contains(beanName)))); }
在获取bean之前如果这个原型bean正在被创建则直接抛出异常。原型bean在创建之前会进⾏标记这个beanName正在被创建,等创建结束之后会删除标记
try { //创建原型bean之前添加标记 beforePrototypeCreation(beanName); //创建原型bean prototypeInstance = createBean(beanName, mbd, args); } finally { //创建原型bean之后删除标记 afterPrototypeCreation(beanName); }
总结:Spring不⽀持原型bean的循环依赖。
Spring 的循环依赖的理论依据基于 Java 的引⽤传递,当获得对象的引⽤时,对象的属性是可以延后设置的,但是构造器必须是在获取引⽤之前Spring通过 setXxx 或者 @Autowired ⽅法解决循环依赖其实是通过提前暴露⼀个 ObjectFactory 对象来完成的,简单来说ClassA 在调⽤构造器完成对象初始化之后,在调⽤ ClassA 的 setClassB ⽅法之前就把ClassA 实例化的对象通过 ObjectFactory 提前暴露到 Spring 容器中。
Spring容器初始化ClassA通过构造器初始化对象后提前暴露到Spring容器。
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isDebugEnabled()) { logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } //将初始化后的对象提前已ObjectFactory对象注⼊到容器中 addSingletonFactory(beanName, new ObjectFactory
ClassA 调⽤ setClassB ⽅法, Spring ⾸先尝试从容器中获取 ClassB ,此时 ClassB 不存在 Spring 容器中。Spring 容器初始化 ClassB ,同时也会将 ClassB 提前暴露到 Spring 容器中ClassB调⽤ setClassA ⽅法, Spring 从容器中获取 ClassA ,因为第⼀步中已经提前暴露了ClassA,因此可以获取到 ClassA 实例ClassA通过 spring 容器获取到 ClassB ,完成了对象初始化操作。
这样 ClassA 和 ClassB 都完成了对象初始化操作,解决了循环依赖问题。
来源:拉钩高薪视频
Spring 容器可以管理 singleton 作用域 Bean 的生命周期,在此作用域下,Spring 能够精确地知道该 Bean 何时被创建,何时初始化完成,以及何时被销毁。
而对于 prototype 作用域的 Bean,Spring 只负责创建,当容器创建了 Bean 的实例后,Bean 的实例就交给客户端代码管理,Spring 容器将不再跟踪其生命周期。每次客户端请求 prototype 作用域的 Bean 时,Spring 容器都会创建一个新的实例,并且不会管那些被配置成 prototype 作用域的 Bean 的生命周期。
了解 Spring 生命周期的意义就在于,可以利用 Bean 在其存活期间的指定时刻完成一些相关操作。这种时刻可能有很多,但一般情况下,会在 Bean 被初始化后和被销毁前执行一些相关操作。
在 Spring 中,Bean 的生命周期是一个很复杂的执行过程,我们可以利用 Spring 提供的方法定制 Bean 的创建过程。
当一个 Bean 被加载到 Spring 容器时,它就具有了生命,而 Spring 容器在保证一个 Bean 能够使用之前,会进行很多工作。Spring 容器中 Bean 的生命周期流程如图 1 所示。
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 将调用该接口的初始化方法 postProcessAfterInitialization()。此时,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 将调用该方法对 Bean 进行销毁。
Spring 为 Bean 提供了细致全面的生命周期过程,通过实现特定的接口或 的属性设置,都可以对 Bean 的生命周期过程产生影响。虽然可以随意配置 的属性,但是建议不要过多地使用 Bean 实现接口,因为这样会导致代码和 Spring 的聚合过于紧密。
1)根据配置情况调用Bean构造方法或工厂方法实例化Bean。
2)利用依赖注入完成Bean中所有属性值的配置注入。