Bean生命周期

1. Bean生命周期

黄色:容器级生命周期接口方法

红色:Bean级生命周期接口方法

蓝色:Bean自身的方法

具体过程如下:

1.通过调用getBean()向容器请求某个Bean时,如果容器注册了InstantiationAwareBeanPostProcessor接口,将调用postProcessBeforeInstantiation().此时可以获得Bean的类型即Bean的Class信息,可以通过beanName过滤某些Bean

default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
	return null;
}

2.根据配置信息采用构造方法或者工厂方法实例化Bean

3.如果容器注册了InstantiationAwareBeanPostProcessor接口,将调用postProcessAfterInstantiation().此时Bean被实例化,但是没有被初始化,属性填充没有发生,第一次获得操作Bean的权限

default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
	return true;
}

4. 如果Bean配置了属性并且容器注册了InstantiationAwareBeanPostProcessor接口,在容器将配置值设置到属性中之前,将调用postProcessPropertyValue(),此时Bean已经被实例,但是没有被初始化,Field此时为默认值即属性未被填充, 获得了第二次操作Bean的机会,此时不要企图修改在xml中配置的属性值,如果修改会发生覆盖,可以修改未在配置文件中配置的属性

default PropertyValues postProcessPropertyValues(
	PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
	    return pvs;
}

5.调用属性设置方法,将配置值设置到属性中

6.如果Bean实现了BeanNameAware接口,则调用setBeanName()将配置文件中对应的名称设置到Bean中

7.如果Bean实现了BeanFactoryAware接口,则调用setBeanFactory()将BeanFactory设置到Bean中,此处可以采用该BeanFactory操作容器中其他的Bean或者向容器中注册bean

8.如果BeanFactory装配了BeanPostProcessor则调用postProcessBeforeInitialization()对Bean进行处理

default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
	return bean;
}

其中bean为当前请求的bean,beanName为当前bean的配置名称,返回对象是当前处理后请求的bean。第三次获得bean的操作权,此时可以修改bean的默认行为。

9.如果bean实现了InitializingBean接口,则调用afterPropertiesSet()

10.如果bean配置init-method方法则执行该方法,此时也可以修改bean的行为

11.如果BeanFactory装配了BeanPostProcessor则调用postProcessAfterInitialization()对Bean进行处理,第五次获得bena的操纵权

default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
	return bean;
}

12.如果bean配置scope=prototype则将bean直接返回给调用者,调用者自己管理bean的生命周期,如果scope=singleton,spring将bean放入IOC容器的缓存池中,并将bean的引用返回给调用者,spring继续对Bean进行后续的生命周期管理

13.如果bean实现了DisposableBean接口且scope=singleton,当容器关闭时将调用destory(),可以在此处编写释放资源,记录日志等操作

14.scope=singleton且配置destory-method,那么spring将执行destory-method指定的方法,完成相关的操作,此处完成bean资源的释放等

BeanPostProcessor在Spring中占据重要的位置,为容器提供了对Bean进行后续加工处理的切入点,Spring容器提供的AOP,动态代理等,都是通过BeanPostProcessor实现的

2 生命周期分类

2.1 Bean自身方法

    构造函数,调用setter设置属性信息,init-method&destory-method所指定的方法

2.2 Bean级生命周期接口方法

    Bean实现了spring提供的有关Bean生命周期的接口eg:BeanNameAwaer,BeanFactoryAwaer,InitializingBean,DisposableBean 

2.3 容器级生命周期接口方法

    Bean实现了spring提供的有关Bean生命周期的接口eg:InstantiationAwareBeanPostProcessor,BeanPostProcessors,一般称它们为后处理器,后处理器接口一般不由bean本身实现,它们对立于bean,实现了类似容器附加装置的形式注册到容器中,并通过接口反射为spring容器扫描识别。Spring容器在创建任何Bean的时候,后处理器都会起作用,后处理器是全局性的,可以通过beanname判断过滤出感兴趣的Bean进行处理

2.4 工厂后处理器接口方法

    包括AspectJWeavingEnabler,CustomAutowireConfigurer,ConfigurationClassPostProcess等。工厂后处理器也是容器级的,在应用上下文装载配置文件后立即调用

3 验证生命周期

3.1 定义bean生命周期以及Bean自身的方法

package bean.lifecycle.entries;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;

public class User implements BeanNameAware, BeanFactoryAware, InitializingBean, DisposableBean {

    private BeanFactory beanFactory;
    private String beanName;
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("BeanFactoryAware:setBeanFactory --> 注入beanFactory属性");
    }

    @Override
    public void setBeanName(String beanName) {
        System.out.println("BeanNameAware:setBeanName --> 注入address属性");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("DisposableBean:destroy");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean:afterPropertiesSet");
    }

    private String name;
    private String address;

    public User() {
        System.out.println("调用构造函数或者工厂方法创建Bean实例");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        System.out.println("注入Name属性");
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        System.out.println("注入address属性");
        this.address = address;
    }

    @Override
    public String toString() {
        return "User Name: " + this.name + ", User Address: " + this.address;
    }


    //自定义init方法,如果bean配置init-method就执,第四次获得Bean的操作权,行否则不执行
    public void inti() {
        System.out.println("调用自定义的init方法,在次数也可以修改bean的行为");
    }

    //自定义destory方法,如果bean配置了destroy-method就执行否则不执行
    public void destory() {
        System.out.println("调用容器销毁Bean的方法后,调用自定义的destory方法,在次数也可以修改bean的行为");
    }

}

3.2 定义容器级Bean生命周期方法

package bean.lifecycle.entries;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;


public class UserBeanPostProcessor implements BeanPostProcessor {

    // 和Bean的初始化相关
    // 第三次获得Bean的操作权,此处可以修改bean的行为
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("UserBeanPostProcessor:postProcessBeforeInitialization -- > 在Bean被初始化之前调用");
        return bean;
    }

    // 和Bean的初始化相关
    // 第五次获得Bean的操作权,此处可以修改bean的行为
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("UserBeanPostProcessor:postProcessBeforeInitialization -- > 在Bean被初始化之后调用");
        return bean;
    }
}
package bean.lifecycle.entries;

import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;

import java.beans.PropertyDescriptor;

//扩展InstantiationAwareBeanPostProcessor适配器InstantiationAwareBeanPostProcessorAdapter提供实现
public class UserInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {

    // 和bean的实例化相关,在bean实例化之前执行
    // 可以根据beanName进行过滤操作
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        System.out.println("InstantiationAwareBeanPostProcessor:postProcessBeforeInstantiation --> 在Beanb被例化之前执行");
        return super.postProcessBeforeInstantiation(beanClass, beanName);
    }

    // 和bean的实例化相关,在bean实例化之后执行,此时Bean已经被实例化
    // 但是没有被初始化,Field此时为默认值即属性未被填充
    // 获得了第一次操作Bean的机会
    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        System.out.println("InstantiationAwareBeanPostProcessor:postProcessAfterInstantiation --> 在Bean被实例化之后执行");
        return super.postProcessAfterInstantiation(bean, beanName);
    }

    // 和Bean设置属性,在bean设置属性前执行,此时Bean已经被实例化
    // 但是没有被初始化,Field此时为默认值即属性未被填充
    // 获得了第二次操作Bean的机会,此时不要企图修改在xml中配置的属性值,如果修改会发生覆盖
    // 可以修改未在配置文件中配置的属性
    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
        System.out.println("InstantiationAwareBeanPostProcessor:postProcessPropertyValues --> 在Bean设置属性前执行");
        return super.postProcessPropertyValues(pvs, pds, bean, beanName);
    }
}

3.3 bean配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="user" class="bean.lifecycle.entries.User" init-method="inti"
          destroy-method="destory">
        <property name="address" value="aajiajiaji"></property>
    </bean>
</beans>

3.4 向容器中注册后处理器

package bean.lifecycle;

import bean.lifecycle.entries.User;
import bean.lifecycle.entries.UserBeanPostProcessor;
import bean.lifecycle.entries.UserInstantiationAwareBeanPostProcessor;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;

public class Main {
    public static void main(String[] args) {
        Resource resource = new ClassPathResource("/bean/lifecycle/config/bean.xml");

        BeanFactory bf = new DefaultListableBeanFactory();
        XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader((DefaultListableBeanFactory)bf);
        xmlBeanDefinitionReader.loadBeanDefinitions(resource);

        //向容器中注册BeanPostProcessor后处理器
        ((ConfigurableBeanFactory) bf).addBeanPostProcessor(new UserBeanPostProcessor());
        //向容器中注册InstantiationAwareBeanPostProcessor后处理器
        ((ConfigurableBeanFactory) bf).addBeanPostProcessor(new UserInstantiationAwareBeanPostProcessor());

        //触发生命周期
        User user = (User) bf.getBean("user");
        System.out.println(user.toString());

        ((DefaultListableBeanFactory) bf).destroySingletons();

    }
}

3.5 输出结果

InstantiationAwareBeanPostProcessor:postProcessBeforeInstantiation --> 在Beanb被例化之前执行
调用构造函数或者工厂方法创建Bean实例
InstantiationAwareBeanPostProcessor:postProcessAfterInstantiation --> 在Bean被实例化之后执行
InstantiationAwareBeanPostProcessor:postProcessPropertyValues --> 在Bean设置属性前执行
注入address属性
BeanNameAware:setBeanName --> 注入address属性
BeanFactoryAware:setBeanFactory --> 注入beanFactory属性
UserBeanPostProcessor:postProcessBeforeInitialization -- > 在Bean被初始化之前调用
InitializingBean:afterPropertiesSet
调用自定义的init方法,在次数也可以修改bean的行为
UserBeanPostProcessor:postProcessBeforeInitialization -- > 在Bean被初始化之后调用
User Name: null, User Address: aajiajiaji
DisposableBean:destroy
调用容器销毁Bean的方法后,调用自定义的destory方法,在此处也可以修改bean的行为

4 bean生命周期总结

实现了Spring的Bean生命周期接口对Bean进行了额外的控制,使Bean具有更细致的生命周期阶段,这使Bean和Spring框架紧紧的绑定在一起。可以采用配置的方式解耦即通过init-method&destory-method指定bean的初始化和销毁方法。采用这种方式和实现InitialzingBean和DisposableBean接口的效果是一样的。此外Spring还提供Bean后置处理器InitDestoryAnnotationBeanPostProcessor,它负责对标注了@PostConstruct,@PreDestory的Bean进行处理,在Bean初始化后以及销毁前执行相应的逻辑。

对于BeanFactoryAware让Bean感知BeanFactory,BeanNameAware获得配置文件中对应的配置名称。一般情况下用户不用关心这两个接口。如果Bean希望获取容器中其他Bean,可以通过配置的方式(属性注入,构造注入)引用这些Bean。如果Bean希望在运行期间获得配置文件中的Bean名称可以将将名称作为属性注入。

后处理器(eg:BeanPostProcessor)它不要求业务Bean继承,可以向插件一样注册到Spring容器中,提供额外的功能,Spring充分利用了后处理器/后置处理器对Bean进行了加工处理。

5 ApplicationContext中Bean的生命周期


Bean在ApplicationContext中生命周期和BeanFactory中的生命周期类似,但是也有区别,主要有如下几点:

1.如果Bean实现了ApplicationContextAware接口则会调用setApplicationContext()接口方法,该接口方法属于Bean级生命周期的方法,让Bean感知应用上下文,获得操作上下文的权利

public interface ApplicationContextAware extends Aware {

	/**
	 * Set the ApplicationContext that this object runs in.
	 * Normally this call will be used to initialize the object.
	 * <p>Invoked after population of normal bean properties but before an init callback such
	 * as {@link org.springframework.beans.factory.InitializingBean#afterPropertiesSet()}
	 * or a custom init-method. Invoked after {@link ResourceLoaderAware#setResourceLoader},
	 * {@link ApplicationEventPublisherAware#setApplicationEventPublisher} and
	 * {@link MessageSourceAware}, if applicable.
	 * @param applicationContext the ApplicationContext object to be used by this object
	 * @throws ApplicationContextException in case of context initialization errors
	 * @throws BeansException if thrown by application context methods
	 * @see org.springframework.beans.factory.BeanInitializationException
	 */
	void setApplicationContext(ApplicationContext applicationContext) throws BeansException;

}
2.如果在配置文件中声明了工厂后处理器接口BeanFactoryPostProcessor的实现类, 在应用上下文装配配置文件之后,初始化Bean实例之前 将调用这些 BeanFactoryPostProcessor对配置文件进行处理。 此处可以采用该BeanFactory操作容器中其他的Bean或者向容器中注册新的Bean 。此时可以通过BeanFactory获得BeanDefinitoin对象,采用BeanDefinitoin可以为某个Bean添加额外的信息(eg:配置新属性)如果在配置文件中配置了多个工厂后处理器,建议这些工厂后处理器实现?Ordered接口,确保Spring以确定的顺序调用这些工厂后处理器。 工厂后处理器是容器级别的Bean生命周期接口。仅在应用上下文初始化时调用一次,目的是完成一些配置文件的处理工作。

ApplicationContext中的bean会利用java反射机制自动识别配置文件中定义的后处理器(eg:BeanPostProcessor,InstantiationAwareBeanPostProcessor)和工厂后处理器(eg:BeanFactoryPostProcessor)并自动将其注册到应用上下文中。

BeanFactory中的Bean需要编码的方式注册这些后处理器(eg:addBeanPostProcessor())

BeanFactoryPostProcessor

允许修改ApplicationContext中定义的Bean的属性。 BeanFactoryPostProcessor可能与bean定义交互并修改,但永远不会实例化bean。 这样做可能会导致bean过早实例化,违反容器并导致意想不到的副作用。

/**
 * Allows for custom modification of an application context's bean definitions,
 * adapting the bean property values of the context's underlying bean factory.
 *
 * <p>Application contexts can auto-detect BeanFactoryPostProcessor beans in
 * their bean definitions and apply them before any other beans get created.
 *
 * <p>Useful for custom config files targeted at system administrators that
 * override bean properties configured in the application context.
 *
 * <p>See PropertyResourceConfigurer and its concrete implementations
 * for out-of-the-box solutions that address such configuration needs.
 *
 * <p>A BeanFactoryPostProcessor may interact with and modify bean
 * definitions, but never bean instances. Doing so may cause premature bean
 * instantiation, violating the container and causing unintended side-effects.
 * If bean instance interaction is required, consider implementing
 * {@link BeanPostProcessor} instead.
 *
 * @author Juergen Hoeller
 * @since 06.07.2003
 * @see BeanPostProcessor
 * @see PropertyResourceConfigurer
 */
@FunctionalInterface
public interface BeanFactoryPostProcessor {

	/**
	 * Modify the application context's internal bean factory after its standard
	 * initialization. All bean definitions will have been loaded, but no beans
	 * will have been instantiated yet. This allows for overriding or adding
	 * properties even to eager-initializing beans.
	 * @param beanFactory the bean factory used by the application context
	 * @throws org.springframework.beans.BeansException in case of errors
	 */
         //标准初始化后,修改应用程序上下文的内部bean工厂。 所有的bean定义都将被加载,但没有bean会被实例化。 这允许重写或添加属性
	void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}

7 示例

7.1 实现工厂后处理接口

public class UserBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
	void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		//获得配置文件中存在的Bean的定义
		BeanDefinition bd = beanFactory.getBeanDefinition(“配置文件存在的Bean”);
		bd.getPropertyValues().addPropertyValue(“属性名称”,”属性值”);
	}
}

ApplicationContext在启动时,首先将配置文件中每个<bean>节点生成一个BeanDefinition对象,该对象是Bean中容器中的内部表示,当配置文件中所有的<bean>节点都被解析称BeanDefinition时,容器调用工厂后处理器方法,此时我们可以调整bean的配置信息

7.2 配置工厂后处理器

工厂后处理器和后处理器的配置和普通bean的配置一样


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值