Spring注解开发(六)——Bean的生命周期以及BeanPostProcessor的源码分析

 

目录

1.指定初始化和销毁方法: 

2.让Bean实现InitializingBean和DisposableBean接口

3.使用JS250规范提供的两个注解

4. BeanPostProcessor(重点):bean的后置处理器

BeanPostProcessor的工作原理(源码分析)


Bean的生命周周期:bean的创建--初始化--销毁的过程

我们可以自定义初始化和销毁方法,容器在bean进行到当前生命周期的时候来调用我们自定义的初始化和销毁方法

对象的创建:单实例在容器启动的时候就创建,多实例在获取该对象的时候创建

对象的初始化:对象创建完成后,并复赋值好,调用初始化方法

对象的销毁:单实例:容器关闭的时候,调用销毁方法

                     多实例:容器不管理,不会调用销毁方法

1.指定初始化和销毁方法: 

通过@Bean指定initMethod和destoryMethod方法

package com.cjian.bean;

/**
 * @description:
 * @author: cWX969834
 * @time: 2020/10/29 14:34
 */
public class Car {
    public Car() {
        System.out.println("Car constructor...");
    }

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

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

配置类:

package com.cjian.config;

import com.cjian.bean.Color;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScans;
import org.springframework.context.annotation.Configuration;

/**
 * @description:
 * @author: cWX969834
 * @time: 2020/10/28 9:32
 */
@Configuration //告诉spring这是一个配置类
@ComponentScans(value = {
    @ComponentScan(value = "com.cjian")
})
public class MainConfig2 {
    @Bean(initMethod = "init",destroyMethod = "destory")
    public Car car(){
        return new Car();
    }

}

测试:

package com.cjian;

import com.cjian.config.MainConfig2;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @description:
 * @author: cWX969834
 * @time: 2020/10/28 9:44
 */
public class Test2 {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(
            MainConfig2.class);
        System.out.println("容器创建完成");
        //关闭容器
        annotationConfigApplicationContext.close();
    }


}

输出:

Car constructor...
Car init...
容器创建完成
Car destory...

以上是单实例的,多实例如下:

package com.cjian.config;

import com.cjian.bean.Color;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScans;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

/**
 * @description:
 * @author: cWX969834
 * @time: 2020/10/28 9:32
 */
@Configuration //告诉spring这是一个配置类
@ComponentScans(value = {
    @ComponentScan(value = "com.cjian")
})
public class MainConfig2 {
    
    @Scope("prototype")
    @Bean(initMethod = "init",destroyMethod = "destory")
    public Color color(){
        return new Color();
    }

}

测试:

package com.cjian;

import com.cjian.config.MainConfig2;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @description:
 * @author: cWX969834
 * @time: 2020/10/28 9:44
 */
public class Test2 {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(
            MainConfig2.class);
        System.out.println("容器创建完成");
        annotationConfigApplicationContext.getBean("car");
        //关闭容器
        annotationConfigApplicationContext.close();

    }


}

输出:

容器创建完成
Car constructor...
Car init...

2.让Bean实现InitializingBean和DisposableBean接口

package org.springframework.beans.factory;

public interface InitializingBean {
    void afterPropertiesSet() throws Exception;
}

package org.springframework.beans.factory;

public interface DisposableBean {
    void destroy() throws Exception;
}
package com.cjian.bean;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

/**
 * @description:
 * @author: cWX969834
 * @time: 2020/10/29 14:34
 */
@Component
//@Scope("prototype")
public class Cat implements InitializingBean, DisposableBean {
    public Cat() {
        System.out.println("Cat constructor...");
    }

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

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("cat init...");

    }
}

测试类:

package com.cjian;

import com.cjian.config.MainConfig2;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @description:
 * @author: cWX969834
 * @time: 2020/10/28 9:44
 */
public class Test2 {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(
            MainConfig2.class);
        System.out.println("容器创建完成");
        //关闭容器
        annotationConfigApplicationContext.close();

    }


}

输出:多实例的就不演示了

Cat constructor...
cat init...
容器创建完成
cat destroy...

 

3.使用JS250规范提供的两个注解

底层是通过后置处理器BeanPostProcessor实现的

 

package com.cjian.bean;

import org.springframework.stereotype.Component;

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

/**
 * @description:
 * @author: cWX969834
 * @time: 2020/10/29 15:06
 */
@Component
public class Dog {

    public Dog() {
        System.out.println("dog constructor...");
    }

    //对象创建并完成赋值之后调用
    @PostConstruct
    public void initial(){
        System.out.println("dog init...");
    }

    //容器移除对象之前调用
    @PreDestroy
    public void destory(){
        System.out.println("dog destory...");
    }
}

输出:

dog constructor...
dog init...
容器创建完成
dog destory..

4. BeanPostProcessor(重点):bean的后置处理器

在bean的初始化前后进行一些处理工作,该接口十分强大,也十分重要,其中postProcessBeforeInitialization方法优于其他任何初始化方法,postProcessAfterInitialization调用在任何其他”销毁“方法之后(后面源码分析)

package org.springframework.beans.factory.config;

import org.springframework.beans.BeansException;
import org.springframework.lang.Nullable;

public interface BeanPostProcessor {
    @Nullable
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

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

编写一个自己的后置处理器

package com.cjian.config;

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

/**
 * @description:
 * @author: cWX969834
 * @time: 2020/10/29 15:20
 */
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitialization:"+beanName+","+bean);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization:"+beanName+","+bean);
        return bean;
    }
}

输出:

postProcessBeforeInitialization:mainConfig2,com.cjian.config.MainConfig2$$EnhancerBySpringCGLIB$$c12b836e@69b794e2
postProcessAfterInitialization:mainConfig2,com.cjian.config.MainConfig2$$EnhancerBySpringCGLIB$$c12b836e@69b794e2
Cat constructor...
postProcessBeforeInitialization:cat,com.cjian.bean.Cat@f0f2775
cat init...
postProcessAfterInitialization:cat,com.cjian.bean.Cat@f0f2775
dog constructor...
postProcessBeforeInitialization:dog,com.cjian.bean.Dog@4d49af10
dog init...
postProcessAfterInitialization:dog,com.cjian.bean.Dog@4d49af10
容器创建完成
dog destory...
cat destroy...

BeanPostProcessor的工作原理(源码分析)

我们首先将断点打在这里:

查看debug一个大概的过程:

1.main方法中启动 AnnotationConfigApplicationContext 容器后,进入该构造函数的refresh方法:

2.初始化所有的单实例对象

 

3.接着调用 preInstantiateSingletons 里的getBean方法去获取对象

下面的getBean

 

4.去获取bean

因为容器刚启动,肯定是获取不到的,所以doGetBean方法里会调用createBean方法去创建对象

5.创建对象并初始化

调用createBean里的doCreateBean方法:

 

再调用到doCreateBean里的

populateBean 方法会先为对象里的所有属性赋好值,然后调用initializeBean去初始化对象,重点来了:

 

第一点就是去执行我们的后置处理器的postProcessBeforeInitialization 方法了,

由截图可知,一旦某个后置处理器的方法返回null,则遍历结束,后边的后置处理器不再被执行

第二点里的执行初始化方法包括:我们写的initMethod、destoryMethod,Bean实现的InitializingBean和DisposableBean接口的方法以及JS250规范提供的两个注解所标注的方法,

第三点就是去执行我们的后置处理器的postProcessAfterInitialization方法了

 

后置处理器在spring的底层被大量使用,看一个例子:

如果我们想在一个类中获取到applicationContext,要怎么做呢?

我们可以让我们的类实现 ApplicationContextAware 接口(PS:XXXAware  为装备XXX的意思)

package org.springframework.context;

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

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




package org.springframework.beans.factory;

public interface Aware {
}
package com.cjian.bean;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

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

/**
 * @description:
 * @author: cWX969834
 * @time: 2020/10/29 15:06
 */
@Component
public class Dog implements ApplicationContextAware {
    private ApplicationContext applicationContext;

    public Dog() {
        System.out.println("dog constructor...");
    }

    //对象创建并完成赋值之后调用
    @PostConstruct
    public void initial(){
        System.out.println("dog init...");
    }

    //容器移除对象之前调用
    @PreDestroy
    public void destory(){
        System.out.println("dog destory...");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

源码如下:


package org.springframework.context.support;

import java.security.AccessControlContext;
import java.security.AccessController;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.EmbeddedValueResolver;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.lang.Nullable;
import org.springframework.util.StringValueResolver;
//这是spring自带的的一个后置处理器
class ApplicationContextAwareProcessor implements BeanPostProcessor {
    private final ConfigurableApplicationContext applicationContext;
    private final StringValueResolver embeddedValueResolver;

    public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
        this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
    }

    @Nullable
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        //判断bean是否属于以下几种,dog实现了ApplicationContextAware接口,
        if (!(bean instanceof EnvironmentAware) && !(bean instanceof EmbeddedValueResolverAware) && !(bean instanceof ResourceLoaderAware) && !(bean instanceof ApplicationEventPublisherAware) && !(bean instanceof MessageSourceAware) && !(bean instanceof ApplicationContextAware)) {
            return bean;
        } else {
            AccessControlContext acc = null;
            if (System.getSecurityManager() != null) {
                acc = this.applicationContext.getBeanFactory().getAccessControlContext();
            }

            if (acc != null) {
                AccessController.doPrivileged(() -> {
                    this.invokeAwareInterfaces(bean);
                    return null;
                }, acc);
            } else {
                this.invokeAwareInterfaces(bean);
            }

            return bean;
        }
    }

    private void invokeAwareInterfaces(Object bean) {
        if (bean instanceof EnvironmentAware) {
            ((EnvironmentAware)bean).setEnvironment(this.applicationContext.getEnvironment());
        }

        if (bean instanceof EmbeddedValueResolverAware) {
            ((EmbeddedValueResolverAware)bean).setEmbeddedValueResolver(this.embeddedValueResolver);
        }

        if (bean instanceof ResourceLoaderAware) {
            ((ResourceLoaderAware)bean).setResourceLoader(this.applicationContext);
        }

        if (bean instanceof ApplicationEventPublisherAware) {
            ((ApplicationEventPublisherAware)bean).setApplicationEventPublisher(this.applicationContext);
        }

        if (bean instanceof MessageSourceAware) {
            ((MessageSourceAware)bean).setMessageSource(this.applicationContext);
        }

       //dog实现了该接口,会调用到dog里面的setApplicationContext方法,真正的applicationContext也是在这里传入的
        if (bean instanceof ApplicationContextAware) {
            ((ApplicationContextAware)bean).setApplicationContext(this.applicationContext);
        }

    }
}

还有@Autowired注解的使用,底层也是后置处理器帮我们完成的(在对象创建完以后帮我们注入属性值)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值