目录
2.让Bean实现InitializingBean和DisposableBean接口
4. BeanPostProcessor(重点):bean的后置处理器
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注解的使用,底层也是后置处理器帮我们完成的(在对象创建完以后帮我们注入属性值)