Spring再次学习(4)

2019-08-16 12:16:59来源:博客园 阅读 ()

新老客户大回馈,云服务器低至5折

Spring再次学习(4)

时隔一年多,在掌握了Spring、SpringBoot、SpringCloud之后

我再次回头,重新学习Spring框架

 

Bean的生命周期学习:

在传统的XML配置中,可以这样自定义初始化和销毁方法:

init-method="" destroy-method=""

 

注解方式的简单使用:

@Configuration
public class LifeCircleConfig {
    @Bean(initMethod = "init",destroyMethod = "destroy")
    public Car car(){
        return new Car();
    }
}
public class Car {
    public Car(){
        System.out.println("Construct Car!");
    }
    public void init(){
        System.out.println("Car init!");
    }
    public void destroy(){
        System.out.println("Car destroy!");
    }
}
public class LifeCircleTest {

    private static AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(LifeCircleConfig.class);

    @Test
    public void test(){
        applicationContext.close();
    }
}

注意:要有close方法,否则不会打印Car销毁方法

 

打印如下:

Construct Car!
Car init!
Car destroy!

 

这里默认的是单实例Bean

如果是多实例的话,按照以上的测试代码是不会打印的,因为多实例情况下,在获取Bean的情况下才会创建对象

而且在多例情况下,只会调用初始化和构造方法,不会调用销毁方法

以上测试代码只完成了初始化IOC容器,所以什么都不打印

 

实现Spring中接口方式:这时候不需要在@Bean中进行配置

public class Car implements InitializingBean, DisposableBean {

    public Car() {
        System.out.println("Construct Car!");
    }

    public void afterPropertiesSet() throws Exception {
        System.out.println("Car init!");
    }

    public void destroy() {
        System.out.println("Car destroy!");
    }

}

 

使用Java原生注解:

public class Car {

    public Car() {
        System.out.println("Construct Car!");
    }

    @PostConstruct
    public void init() {
        System.out.println("Car init!");
    }

    @PreDestroy
    public void destroy() {
        System.out.println("Car destroy!");
    }

}

 

使用Spring中Bean的后置处理器:

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    /**
     * 初始化前调用
     */
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitialization " + bean + " " + beanName);
        return bean;
    }

    /**
     * 初始化后调用
     */
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization " + bean + " " + beanName);
        return bean;
    }
}
@Configuration
@ComponentScan("org.dreamtech.bean")
public class LifeCircleConfig {
    @Bean
    public Car car(){
        return new Car();
    }
}

 

测试后部分打印如下:

Construct Car!
postProcessBeforeInitialization org.dreamtech.bean.Car@2d9d4f9d car
postProcessAfterInitialization org.dreamtech.bean.Car@2d9d4f9d car

 

BeanPostProcessor原理:

查看这一段源码:

initializeBean(beanName, exposedObject, mbd)方法中:

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

        try {
            invokeInitMethods(beanName, wrappedBean, mbd);
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    (mbd != null ? mbd.getResourceDescription() : null),
                    beanName, "Invocation of init method failed", ex);
        }

        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }

在invokeInitMethods初始化方法之前

调用了applyBeanPostProcessorsBeforeInitialization,也就是调用了所有PostProcessor的Before方法

在invokeInitMethods初始化方法之后

调用了applyBeanPostProcessorsAfterInitialization,也就是调用了所有PostProcessor的After方法

 

进入applyBeanPostProcessorsBeforeInitialization方法查看源码:

遍历所有的Processor,一旦返回null,就会跳出循环

    @Override
    public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
            throws BeansException {

        Object result = existingBean;
        for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
            result = beanProcessor.postProcessBeforeInitialization(result, beanName);
            if (result == null) {
                return result;
            }
        }
        return result;
    }

 

在initializeBean方法之前,调用的是populateBean方法

作用:给属性赋值

        // Initialize the bean instance.
        Object exposedObject = bean;
        try {
            populateBean(beanName, mbd, instanceWrapper);
            if (exposedObject != null) {
                exposedObject = initializeBean(beanName, exposedObject, mbd);
            }
        }

 

所以:BeanPostProcessor是在Bean赋值之后,初始化的过程前后执行的

 

BeanPostProcessor在Spring底层的使用:

获取IOC容器的接口:

public interface ApplicationContextAware extends Aware {
    void setApplicationContext(ApplicationContext var1) throws BeansException;
}

而它就是基于BeanPostProcessor的,代码过长就不截取了

class ApplicationContextAwareProcessor implements BeanPostProcessor

 

或者是参数校验:也使用到了BeanPostProcessor

public class BeanValidationPostProcessor implements BeanPostProcessor, InitializingBean

部分代码如下:

    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (!this.afterInitialization) {
            this.doValidate(bean);
        }

        return bean;
    }

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (this.afterInitialization) {
            this.doValidate(bean);
        }

        return bean;
    }

 


原文链接:https://www.cnblogs.com/xuyiqing/p/11307820.html
如有疑问请与原作者联系

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:方法重载

下一篇:SpringBoot:如何优雅地处理全局异常?