Spring再次学习

Posted xuyiqing

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring再次学习相关的知识,希望对你有一定的参考价值。

时隔一年多,在掌握了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;
    

 

以上是关于Spring再次学习的主要内容,如果未能解决你的问题,请参考以下文章

战斗伊始——Spring

我的第一个spring boot程序(spring boot 学习笔记之二)

spring微服务全家桶基础入门学习指南

spring微服务全家桶基础入门学习指南

spring微服务全家桶基础入门学习指南

Spring中的IOC