Spring源码阅读(四)

我们知道,在spring bean生命周期中,我们可以在不同阶段执行处理器或者方法,比如init-method,destroy方法,BeanPostProcessor接口等。那么这些处理器或方法的执行顺序是怎样的,让我们用实际例子来观察。

package com.coshaho.learn.spring;

import java.util.HashMap;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.AnnotatedGenericBeanDefinition;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;

/**
 * 
 * ASpringProcessor.java Create on 2017年10月17日 下午10:06:35    
 *    
 * 类功能说明: Spring处理器执行顺序
 *
 * Copyright: Copyright(c) 2013 
 * Company: COSHAHO
 * @Version 1.0
 * @Author coshaho
 */
@Component("springProcessor")
@DependsOn("dependsBean")
@ComponentScan("com.coshaho.learn.spring")
public class ASpringProcessor implements InitializingBean, DisposableBean, BeanNameAware
{
    @Autowired
    public BAutowiredBean autowiredBean;
    
    public ASpringProcessor()
    {
        System.out.println("SpringProcessor construct. x is " + x + ".");
    }
    
    // BeanNameAware
    public void setBeanName(String name) 
    {
        System.out.println("Call BeanNameAware setBeanName, name is " + name + ", x is " + x + ".");
    }

    // DisposableBean
    public void destroy() throws Exception 
    {
        System.out.println("Call DisposableBean destroy.");
    }
    
    // InitializingBean
    public void afterPropertiesSet() throws Exception 
    {
        System.out.println("Call InitializingBean afterPropertiesSet.");
    }
    
    @PostConstruct 
    public void postConstruct() 
    {
        System.out.println("Call postConstruct method.");
    }

    @PreDestroy
    public void preDestroy() 
    {
        System.out.println("Call preDestroy method.");
    }
    
    public void initMethod() 
    {
        System.out.println("Call manually initMethod.");
    }

    public void destroyMethod() 
    {
        System.out.println("Call manually destroyMethod.");
    }
    
    public void sayHello()
    {
        System.out.println("Hello, Spring.");
    }

    @Value("cauchy")
    private String x;
    public void setX(String x) 
    {
        this.x = x;
    }
    
    public static void main(String[] args) throws Exception 
    {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring.xml");
        ASpringProcessor springBean = (ASpringProcessor)context.getBean("springProcessor");
        springBean.sayHello();
        context.close();
        
        System.out.println();
        
        // 创建一个BeanFactory
        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
        factory.addBeanPostProcessor(new EBeanPostProcessor());

        // 构造一个BeanDefinition
        AnnotatedGenericBeanDefinition beanDefinition=new AnnotatedGenericBeanDefinition(ASpringProcessor.class);
        beanDefinition.setInitMethodName("initMethod");
        beanDefinition.setDestroyMethodName("destroyMethod");

        // 设置这个bean的属性
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("x", "coshaho");
        beanDefinition.setPropertyValues(new MutablePropertyValues(map));

        // 注册BeanDefinition
        factory.registerBeanDefinition("springProcessor", beanDefinition);

        // 执行获取和销毁bean的方法
        factory.getBean("springProcessor");
        factory.destroySingleton("springProcessor");
    }
}


package com.coshaho.learn.spring;

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

class EBeanPostProcessor implements BeanPostProcessor 
{
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException 
    {
        System.out.println("MyBeanPostProcessor postProcessBeforeInitialization.");
        return bean;
    }

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException 
    {
        System.out.println("MyBeanPostProcessor postProcessAfterInitialization.");
        return bean;
    }
} 
package com.coshaho.learn.spring;

import org.springframework.stereotype.Service;

@Service
public class BAutowiredBean 
{
    public BAutowiredBean()
    {
        System.out.println("AutowiredBean construct.");
    }

}

package com.coshaho.learn.spring;

import org.springframework.stereotype.Service;

@Service("dependsBean")
public class CDependsBean 
{
    public CDependsBean()
    {
        System.out.println("DependsBean construct.");
    }

}

执行结果

Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@7cef4e59: startup date [Tue Oct 17 18:18:23 GMT+08:00 2017]; root of context hierarchy
Loading XML bean definitions from class path resource [spring.xml]
DependsBean construct.
SpringProcessor construct. x is null.
AutowiredBean construct.
Call BeanNameAware setBeanName, name is springProcessor, x is cauchy.
Call postConstruct method.
Call InitializingBean afterPropertiesSet.
Hello, Spring.
Closing org.springframework.context.support.ClassPathXmlApplicationContext@7cef4e59: startup date [Tue Oct 17 18:18:23 GMT+08:00 2017]; root of context hierarchy
Call preDestroy method.
Call DisposableBean destroy.

SpringProcessor construct. x is null.
Call BeanNameAware setBeanName, name is springProcessor, x is coshaho.
MyBeanPostProcessor postProcessBeforeInitialization.
Call InitializingBean afterPropertiesSet.
Call manually initMethod.
MyBeanPostProcessor postProcessAfterInitialization.
Call DisposableBean destroy.
Call manually destroyMethod.

可以看出来,spring bean加载顺序如下

1. 初始化depends bean;

2. 执行bean构造方法;

3. 初始化依赖注入bean;

4. 其他属性赋值;

5. 执行BeanNameAware接口的setBeanName方法;

6. 执行BeanPostProcessor接口postProcessBeforeInitialization方法;

7. 执行@PostConstruct注解方法;

8. 执行InitializingBean接口的afterPropertiesSet方法;

9. 执行init-method方法;

10. 执行BeanPostProcessor接口postProcessAfterInitialization方法;

11. 执行@PreDestroy注解方法;

12. 执行DisposableBean接口的destroy方法;

13. 执行destroy-method方法。

原文地址:https://www.cnblogs.com/coshaho/p/7684370.html