zoukankan      html  css  js  c++  java
  • Spring BeanPostProcessor分析

    BeanPostProcessor的概念容易与BeanFactoryPostProcessor的概念混淆,看上去都是以PostProcessor,但两者不是同一个概念,用处也不同;BeanPostProcessor是存在于对象实例化后,进行初始化的阶段BeanFactoryPostProcessor则是存在于容器启动阶段;

    BeanPostProcessor为bean的后置处理器,在bean初始化之前调用进行拦截,在bean初始化前后进行一些处理工作 ,说明此时的bean已经进行了实例化;

    BeanPostProcessor接口声明了两个方法,分别在两个不同的时机执行;BeanPostProcessor的两个方法中都传入了原来的对象实例的引用,这为使用者扩展容器的对象实例化过程中的行为提供了极大的便利,使用者几乎可以对传入的对象实例执行任何的操作;

    以下Spring版本为5.2.4.RELEASE


    org.springframework.context.support.AbstractApplicationContext#refresh是Spring中一个很重要的方法,它用来加载配置,完成Spring上下文初始化工作,而refresh方法在org.springframework.context.ConfigurableApplicationContext接口定义;

    • org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization

      

      postProcessBeforeInitialization方法是BeanPostProcessor前置处理这一步将会执行的方法,该方法会在org.springframework.beans.factory.InitializingBean#afterPropertiesSet或自定义init-method方法执行;

      org.springframework.beans.factory.InitializingBean#afterPropertiesSet,在初始化bean的时候执行,可以针对某个具体的bean进行自定义配置;

      

        不过afterPropertiesSet方法是优先于init-method执行;

      init-method方式有两种,如下;

        • @Bean注解的initMethod属性添加该类自定义的初始化方法;  

          org.springframework.context.annotation.Bean#initMethod

        

      • Spring支持 JSR-250,可在该类自定义的初始化方法上添加@PostConstruct注解

          @PostConstruct:在bean创建完成(即在构造方法执行完毕后执行),且属于赋值完成后进行初始化,属于JDK规范的注解;
          @PreDestroy:在bean将被移除之前进行通知,在容器销毁之前进行清理工作;

          这两个注解org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor是在这里进行处理的;

        

        参考:[https://docs.spring.io/spring-framework/docs/5.2.4.RELEASE/spring-framework-reference/core.html#beans-factory-lifecycle]   

       

    • org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization

      

       postProcessAfterInitialization方法是BeanPostProcessor后置处理那一步将会执行的方法,该方法会在org.springframework.beans.factory.InitializingBean#afterPropertiesSet自定义init-method方法执行;

    • 具体调用,如下

      org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)

      bean在实例化后,进入初始化阶段;

      

      org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeInitMethods 

      该方法里面会有调用afterPropertiesSetinvokeCustomInitMethod

      afterPropertiesSet方法对实现了InitializingBean接口的类可以进行自定义初始化配置,在构造方法执行;

      invokeCustomInitMethod也是可以进行自定义初始化配置,在构造方法执行,不需要实现InitializingBean接口;

      自定义的init-method是在org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForBeanMethod设置的;

      

      该方法是在org.springframework.context.support.AbstractApplicationContext#invokeBeanFactoryPostProcessors里面进行调用的,里面执行的是执行BeanFactoryPostProcessor的方法;

      前面说到afterPropertiesSet方法执行优先于init-method,具体如下;

      

      而invokeCustomInitMethod里面调用的是BeanDefinitioninit-method方法;

      

       org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization

       该方法在自定义初始化配置执行;遍历对应的Processors,并执行它相应的postProcessorsBeforeInitialization方法;

       

      org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization

      该方法在自定义初始化配置执行;遍历对应的Processors,并执行它相应的postProcessorsAfterInitialization方法;

      

      它的调用格式如下,这个相当于AOP,在invokeInitMethods的前后进行方法增强;

    applyBeanPostProcessorsBeforeInitialization
    
    invokeInitMethods
    
    applyBeanPostProcessorsAfterInitialization
    
    • 测试代码

      Person2类

    public class Person2 implements InitializingBean {
    	private static final Logger logger = LoggerFactory.getLogger(Person2.class);
    
    	private String name;
    	private Integer age;
    
    	public Person2() {
    		logger.info("person2 constructor none params...");
    	}
    
    	public Person2(String name, Integer age) {
    		super();
    		this.name = name;
    		this.age = age;
    
    		logger.info("person2 constructor all params...");
    	}
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	public Integer getAge() {
    		return age;
    	}
    
    	public void setAge(Integer age) {
    		this.age = age;
    	}
    
    	public void init() {
    		logger.info("person2 init... " + this);
    	}
    
    	public void destory() {
    		logger.info("person2 destroy...");
    	}
    
    	@Override
    	public String toString() {
    		return "Person [name=" + name + ", age=" + age + "]";
    	}
    
    	@Override
    	public void afterPropertiesSet() throws Exception {
    		logger.info("afterPropertiesSet..");
    	}
    }
    

      

      LifeCycleConfig1类

    @Configuration
    @Import(value = {DemoBeanPostProcessor.class})
    public class LifeCycleConfig1 {
    
    	@Bean(initMethod = "init", destroyMethod = "destory")
    	public Person2 person2() {
    		return new Person2("dev", 33);
    	}
    }
    

      DemoBeanPostProcessor类

    @Component
    public class DemoBeanPostProcessor implements BeanPostProcessor {
    	private final static Logger logger = LoggerFactory
    			.getLogger(DemoBeanPostProcessor.class);
    
    	@Override
    	public Object postProcessBeforeInitialization(Object bean, String beanName)
    			throws BeansException {
    		// 返回一个的对象(传过来的对象)
    		// 在初始化方法调用之前进行后置处理工作,
    		// 什么时候调用它: init-method=init之前调用
    		logger.info("postProcessBeforeInitialization...." + beanName + "..." + bean);
    		return bean;
    	}
    
    	@Override
    	public Object postProcessAfterInitialization(Object bean, String beanName)
    			throws BeansException {
    		logger.info("postProcessAfterInitialization...." + beanName + "..." + bean);
    		return bean;
    	}
    }
    

      

      测试类

    @Test
    public void lifeCycleTest1() {
    	AnnotationConfigApplicationContext context =
    			new AnnotationConfigApplicationContext(LifeCycleConfig1.class);
    
    	System.out.println("IOC容器创建完成...");
    	context.close();
    }
    

      

      执行结果如下:

  • 相关阅读:
    【python笔记】类
    【Marva Collins' Way】第八章
    【Marva Collins' Way】第七章
    【python笔记】包
    【python笔记】模块
    【Marva Collins' Way】第六章
    【Marva Collins' Way】第九章
    【python笔记】异常
    Axios跨域&封装接口
    js更新数据
  • 原文地址:https://www.cnblogs.com/coder-zyc/p/14509255.html
Copyright © 2011-2022 走看看