这里要介绍的是Spring的扩展类点之一的:BeanPostProcessor. 废话不多说,开搞!
1.准备代码
- TestProcessor类
@Component
public class TestProcessor implements BeanPostProcessor ,PriorityOrdered{@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if (beanName.equals("personService")){System.out.println("BeforeInitialization1");}return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (beanName.equals("personService")){System.out.println("AfterInitialization1");}return bean;}@Overridepublic int getOrder() {return 200;}
}
- TestProcessor2类
@Component
public class TestProcessor2 implements BeanPostProcessor,PriorityOrdered {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if (beanName.equals("personService")){System.out.println("BeforeInitialization2");}return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (beanName.equals("personService")){System.out.println("AfterInitialization2");}return bean;}@Overridepublic int getOrder() {return 199;}
}
- PersonService类
@Component
public class PersonService {public PersonService() {System.out.println("personService构造方法执行了");}@PostConstructpublic void init(){System.out.println("init方法执行了");}
}
- PersonService2类
@Component
public class PersonService2 implements ApplicationContextAware {private ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;System.out.println("全局对象:"+ applicationContext);}
}
- SpringConfiguration类
@ComponentScan("com.v1")
public class SpringConfiguration {}
- Test01类
public class Test01 {public static void main(String[] args) {//这个构造方法会把Spring所有的环境都准备好AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);}
}
2.点击 AnnotationConfigApplicationContext
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {//这个类有父类,所以会先初始化父类的构造方法,接着初始化自己的构造方法//调用无参构造方法进行初始化一个读取器和扫描仪this();//把配置类加载进 DefaultListableBeanFactory 的map集合中//配置类可以一次性传多个,这个方法执行后,只是把配置类加载进了 DefaultListAbleBeanFactory的map集合中//还没有扫描其他的的加了组件的类register(annotatedClasses);//实例化所有被加了组件的对象refresh();
}
3.点击 refresh()
方法
@Override
public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {//调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识//这个方法不是重点,可以暂时认为他不干任何事情prepareRefresh();//获取工厂对象 ,本质是DefaultListableBeanFactory对象//其实读取xml文件变成beanDefinition,也是在这里面完成的//所以这里面的功能和register(annotatedClasses);功能很像//一个是是从xml文件中读取配置信息,一个是通过类的注解读取信息ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();//为BeanFactory配置类加载器、后置处理器等等//这个方法比较重要prepareBeanFactory(beanFactory);//剩余的代码省略.....}
4.点击 prepareBeanFactory
方法
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {//添加一个类加载器beanFactory.setBeanClassLoader(getClassLoader());//bean的表达式解析,以后再讲,在前台页面可以获取到bean表达式的一些属性beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));//对象与string类型的转换 <property >beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));//重要方法//为Spring添加后置处理器 ApplicationContextAwareProcessor 实现了BeanProcessor接口//我们主要查看 重写接口的 postProcessBeforeInitialization ()方法//主要作用:判断当前bean对象实现了里面的那些接口,从而在bean类获取对应的对象//一般我们会实现 ApplicationContextAware 接口获取 applicationContextbeanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));//以下是添加自动注入忽略的列表,不是重点beanFactory.ignoreDependencyInterface(EnvironmentAware.class);beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);beanFactory.ignoreDependencyInterface(MessageSourceAware.class);beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);//等讲到bean的实例化的过程时,会说明beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);beanFactory.registerResolvableDependency(ResourceLoader.class, this);beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);beanFactory.registerResolvableDependency(ApplicationContext.class, this);//这个ApplicationListenerDetector作用: 某个类实现了ApplicationListener接口,可以获取到一个ApplicationEvent对象//ApplicationEvent对象存储有reader,scanner,registry,beanFactory等对象//注意实现ApplicationListener的前提是,这个bean必须是单例的beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));//剩余的代码省略.....
}
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
解析这个方法之前,我们看一下 BeanFactory
工厂里面到底存放了哪些数据
粉色部分就是 BeanFactory
的示意图
- 绿色部分: Spring初始化的时候,所有的
beanDefinition
都存储在这个beanDefinitionMap
集合中 - 黄色部分:
beanDefinitionNames
集合存储所有beanDefinition
的名称 - 深紫部分:
beanPostProcessors
集合存储着所有的后置处理器,也就是实现了BeanPostProcessor
接口的类 - 浅绿部分:
getBeanNamesForType
,beanFactory
中的一个方法,通过类型得到一个beanName - 浅紫部分:
singletonObjects
,实例化后的类会存储在这个集合中
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this))
这个方法把 ApplicationContextAwareProcessor
添加进了 beanPostProcessors
,说明这个类是一个实现了
BeanPostProcessors
的后置处理器
5.点击 ApplicationContextAwareProcessor
`
查看 ApplicationContextAwareProcessor
,果然它实现了 BeanPostProcessor
6.点击 BeanPostProcessor
public interface BeanPostProcessor {/* * 在bean的初始化之前执行*/@Nullabledefault Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return bean;}/** 在bean的初始化之后执行*/@Nullabledefault Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {return bean;}}
BeanPostProcessor
是Spring框架提供的一个扩展类点之一- 扩展类点其实有很多种的 例如实现
BeanFactoryPostProcessor
接口也是 BeanPostProcessor
作用:- 通过实现
BeanPostProcessor
接口,程序员就可以插手bean的实例化过程,从而减轻beanFactory的负担 - 这个接口可以被多个类实现,会形成一个列表, 通过实现
PriorityOrdered
可以改变实现类的执行顺序,getOrder返回值越小越优先执行 - AOP的就是在bean实例化后期将切面逻辑织入bean实例中的
- AOP也是通过
BeanPostProcessor
和IOC容器建立起了联系
- 通过实现
Spring默认提供很多BeanPostProcessor的实现类
其实这个接口的本身方法特别的简单,简单到令人发指,但是他的实现类巨多,实现类的方法内的逻辑复杂的程 度也令人发指
前面我们准备了两个处理器 TestProcessor
,TestProcessor2
都实现了 BeanPostProcessor
和 PriorityOrdered
- TestProcessor类
@Component
public class TestProcessor implements BeanPostProcessor ,PriorityOrdered{@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {//所有的类的实例化过程中都会执行执行实现了BeanPostProcessor后置处理器//为了避免其他类做实例化的时候,也打印BeforeInitialization1,影响测试if (beanName.equals("personService")){System.out.println("BeforeInitialization1");}return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (beanName.equals("personService")){System.out.println("AfterInitialization1");}return bean;}@Overridepublic int getOrder() {return 200;}
}
- TestProcessor2类
@Component
public class TestProcessor2 implements BeanPostProcessor,PriorityOrdered {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if (beanName.equals("personService")){System.out.println("BeforeInitialization2");}return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (beanName.equals("personService")){System.out.println("AfterInitialization2");}return bean;}@Overridepublic int getOrder() {return 199;}
}
两个后置处理器都实现了 BeanPostProcessor
的init和after方法,实现了 PriorityOrdered
的 getOrder
方法
实现 getOrder
的后置处理器,返回值为 int 类型,返回值越小,执行的顺序越靠前
我们回到 Test01
运行测试类
测试结果:
personService构造方法执行了
BeforeInitialization2
BeforeInitialization1
init方法执行了
AfterInitialization2
AfterInitialization1
全局对象:org.springframework.context.annotation.AnnotationConfigApplicationContext@100955a, started on Sun Dec 08 11:48:03 CST 2019
7.我们回到 ApplicationContextAwareProcessor
类中
既然我们已经知道了 BeanPostProcessors
的作用,我们看看 ApplicationContextAwareProcessor
这个Spring内部的后置处理器的init方法和after方法里面到底干了哪些事
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());}@Override@Nullablepublic Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {AccessControlContext acc = null;//这个方法不会进入if (System.getSecurityManager() != null &&(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {acc = this.applicationContext.getBeanFactory().getAccessControlContext();}if (acc != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {invokeAwareInterfaces(bean);return null;}, acc);}else {//这个重点invokeAwareInterfaces(bean);}return bean;}/*** 判断当前的bean,实现了什么类型的接口,然后根据判断设置类* @param bean*/private void invokeAwareInterfaces(Object bean) {if (bean instanceof Aware) {//(1)如果bean实现了EnvironmentAware接口,可以获取环境对象if (bean instanceof EnvironmentAware) {((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());}//(2)如果bean实现了EmbeddedValueResolverAware接口,可以获取embeddedValueResolver对象if (bean instanceof EmbeddedValueResolverAware) {((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);}//(3)如果bean实现了ResourceLoaderAware接口,可以获取applicationContext工厂对象if (bean instanceof ResourceLoaderAware) {((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);}//(4)如果bean实现了ApplicationEventPublisherAware接口,可以获取applicationContext工厂对象if (bean instanceof ApplicationEventPublisherAware) {((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);}//(5)如果bean实现了MessageSourceAware接口,可以获取applicationContext工厂对象if (bean instanceof MessageSourceAware) {((MessageSourceAware) bean).setMessageSource(this.applicationContext);}//(6)如果该bean实现了ApplicationContextAware接口 ,那么就把工厂applicationContext,传进去
//在bean的类中重写ApplicationContextAware的set方法 就可以在该bean中获取到整个工厂
//这时候想获取哪个对象都可以了if (bean instanceof ApplicationContextAware) {((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);}}}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) {return bean;}}
通过查看 ApplicationContextAwareProcessor
处理器,我们发现 ,它同样是实现了 BeanPostFactory
的两个方法 postProcessBeforeInitialization
和 postProcessAfterInitialization
方法,但是 后置方法并没有干任何事,我们重点查看 前置方法
在 ApplicationContextAwareProcessor
方法中,调用 invokeAwareInterfaces
方法,
查看 invokeAwareInterfaces
方法,我们查询,只要实现某一个接口就能获取相应的对象
例如在准备代码中,我们的 PersonService2
实现了 ApplicationContextAware
接口
@Component
public class PersonService2 implements ApplicationContextAware {private ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;System.out.println("全局对象:"+ applicationContext);}
}
实现了 setApplicationContext
就可以获取全局对象
假设你这样一个需求,需要初始化的时候获取到Spring的全局对象,那么你就可以实现 ApplicationContextAware
总结一下 ApplicationContextAwareProcessor
到底干了哪些事?
- 实现了
BeanPostProcessors
接口 - 在
postProcessBeforeInitialization
方法里面执行invokeAwareInterfaces
方法 - 在
invokeAwareInterfaces
方法中,判断当前的Bean实现了哪些接口,如果实现了某个接口就可以获取对应的对象
8.我们回到 第四步 点击 prepareBeanFactory
`方法
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {//添加一个类加载器beanFactory.setBeanClassLoader(getClassLoader());//bean的表达式解析,以后再讲,在前台页面可以获取到bean表达式的一些属性beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));//对象与string类型的转换 <property >beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));//重要方法//为Spring添加后置处理器 ApplicationContextAwareProcessor 实现了BeanProcessor接口//我们主要查看 重写接口的 postProcessBeforeInitialization ()方法//主要作用:判断当前bean对象实现了里面的那些接口,从而在bean类获取对应的对象//一般我们会实现 ApplicationContextAware 接口获取 applicationContextbeanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));//以下是添加自动注入忽略的列表,不是重点beanFactory.ignoreDependencyInterface(EnvironmentAware.class);beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);beanFactory.ignoreDependencyInterface(MessageSourceAware.class);beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);//等讲到bean的实例化的过程时,会说明beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);beanFactory.registerResolvableDependency(ResourceLoader.class, this);beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);beanFactory.registerResolvableDependency(ApplicationContext.class, this);//这个ApplicationListenerDetector作用: 某个类实现了ApplicationListener接口,可以获取到一个ApplicationEvent对象//ApplicationEvent对象存储有reader,scanner,registry,beanFactory等对象//注意实现ApplicationListener的前提是,这个bean必须是单例的beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));//剩余的代码省略.....
}
在该方法中 ,不仅添加了 ApplicationContextAwareProcessor
,这个后置处理器,其实还添加了 ApplicationListenerDetector
这个处理器
9.点击 ApplicationListenerDetector
我们主要查看 postProcessAfterInitialization
方法
@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) {//判断当前的bean是否实现了ApplicationListener这个接口,如果没有实现直接跳过if (bean instanceof ApplicationListener) {//如果有实现,则判断当前的bean实现是单例的//singletonNames存储用户所有的bean,// key值为 beanName ,value值为Boolean值 false 代表为不是单例 true代表为单例Boolean flag = this.singletonNames.get(beanName);if (Boolean.TRUE.equals(flag)) {this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);}else if (Boolean.FALSE.equals(flag)) {if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) {// inner bean with other scope - can't reliably process eventslogger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface " +"but is not reachable for event multicasting by its containing ApplicationContext " +"because it does not have singleton scope. Only top-level listener beans are allowed " +"to be of non-singleton scope.");}//如果不是单例的,删除掉this.singletonNames.remove(beanName);}}return bean;}
这个方法主要作用:
执行了 ApplicationListener
,必须是 单例的,才可以获取到相应的对象
视频讲解:
<https://www.bilibili.com/video/av67899876?p=4>
视频为自己学习的时候录制的,也方便自己以后看
Spring5源码地址:
<https://gitee.com/zouchangfu/spring_5_source_code>
Spring5源码都是已经构建好的了,无需再使用gradle进行构建了,直接打开就可以跑起来