一、利用后置处理器扩展Spring容器
Bean后置处理器(BeanPostProcessor 接口)
如果希望在Spring容器完成实例化、配置和初始化bean之后实现某些自定义逻辑, 则可以实现一个或多个 BeanPostProcessor 接口。BeanPostProcessor中有两个抽象方法:
- postProcessBeforeInitialization方法:在初始化方法(InitializingBean的afterPropertiesSet、init-method指定的方法等)之前调用
- postProcessAfterInitialization方法:在初始化方法(InitializingBean的afterPropertiesSet、init-method指定的方法等)之后调用
/**
* 后置处理器:初始化前后进行处理工作
*/
@Component //将后置处理器加入容器中
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessBeforeInitialization"+beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessAfterInitialization"+beanName);
return bean;
}
}
BeanPostProcessor中的方法何时别执行?在refresh()方法中调用finishBeanFactoryInitialization(beanFactory), 直到org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
类的doCreateBean方法,该方法中有以下代码:
//给bean属性赋值
populateBean(beanName, mbd, instanceWrapper);
initializeBean(beanName, exposedObject, mbd);
initializeBean方法瞟一眼,内容大致如下:
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
...
//遍历容器中所有的BeanPostProcessor,依次执行postProcessBeforeInitialization,一旦返回null,
//就跳出for循环,不会执行后面的BeanPostProcessor.postProcessBeforeInitialization方法
applyBeanPostProcessorsBeforeInitialization(bean, beanName);
//执行初始化
invokeInitMethods(beanName, wrappedBean, mbd);
// 与applyBeanPostProcessorsBeforeInitialization方法类似
applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
...
return wrappedBean;
}
/**
* 在调用invokeInitMethods方法前调用,处理给中Aware接口
*/
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
invokeInitMethods方法
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd) throws Throwable {
...
((InitializingBean)bean).afterPropertiesSet();
...
invokeCustomInitMethod(beanName, bean, mbd); //通过反射执行
...
}
InitializingBean和init-method可以一起使用,Spring总是先执行InitializingBean的.afterPropertiesSet方法,然后才处理init-method。如果在Spirng处理InitializingBean时出错,那么Spring将直接抛出异常,不会再继续处理init-method。
Ordered 接口与@Order 注解
此接口只有一个方法 int getOrder() 用来设置执行顺序。如果实现多个 BeanPostProcessor 接口, 我们就可以实现 Ordered 接口来设置执行顺序.
@Component
public class Test implements BeanPostProcessor, Ordered {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Override
public int getOrder() {
return 1;
}
}
也可以使用 @Order 注解进行排序·
@Configuration
@Order(2)
public class Demo1Config {
@Bean
public Demo1Service demo1Service(){
System.out.println("demo1config 加载了");
return new Demo1Service();
}
}
设置数值越小优先级越高.
容器后处理器(BeanFactoryPostProcessor 接口)
BeanPostProcessor是bean后置处理器,bean创建对象初始化前后进行拦截工作。
BeanFactoryPostProcessor是beanFactory的后置处理器;在BeanFactory标准初始化之后调用,也就是所有的bean定义已经保存加载到beanFactory,但是bean的实例还未创建。
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor{
//这个方法会在bean实例创建之前调用
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("postProcessBeanFactory...");
String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
int beanDefinitionCount = beanFactory.getBeanDefinitionCount();
System.out.println("当前beanFactory中有"+ beanDefinitionCount +"个bean,这些bean的名字是"+Arrays.toString(beanDefinitionNames));
}
}
BeanFactoryPostProcessor原理:
1)容器创建时调用refresh()方法
2) invokeBeanFactoryPostProcessor(beanFactory),直接在beanFactory中找到所有类型是BeanFactoryPostProcessor的组件,并执行它们的方法,这是在初始化创建其他组件之前执行的。
BeanFactoryPostProcessor 子接口 BeanDefinitionRegistryPostProcessor
BeanDefinitionRegistryPostProcessor是一个接口继承BeanFactoryPostProcessor
BeanDefinitionRegistryPostProcessorpostProcessBeanDefinitionRegistry();这个方法是在所有bean定义信息将要被加载,bean实例还未创建是执行;
- 优先于BeanFactoryPostProcessor执行;
- 利用BeanDefinitionRegistryPostProcessor给容器中再额外添加一些组件
@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor{
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
int beanDefinitionCount = beanFactory.getBeanDefinitionCount();
System.out.println("当前beanFactory中有"+ beanDefinitionCount +"个bean");
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
System.out.println("当前beanFactory中有"+ registry.getBeanDefinitionCount() +"个bean");
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Dog.class).getBeanDefinition();
registry.registerBeanDefinition("newAddBean", beanDefinition);
}
}
原理:
- ioc容器创建执行refresh()方法
- refresh()方法中调用invokeBeanFactoryPostProcessors(beanFactory)
- 从容器中获取到所有的BeanDefinitionRegisryPostProcessor组件,依次触发所有的postProcessBeanDefinitionRegistry()方法,
- 再从容器中找到BeanFactoryPostProcessor组件,然后依次触发postProcessBeanFactory()方法
二、ApplicationListener
监听容器发布的事件,实现一个监听器的步骤:
- 编写一个监听器(实现ApplicationListener类)来监听某个事件(ApplicationEvent极其子类)
- 把监听器加入到容器中
- 只要容器中有相关事件发布,就能监听到这个事件
ContextRefreshedEvent : 容器刷新完成(所有bean都完成创建)会发布这个事件
ContextClosedEvent : 关闭容器会发布这个事件 - 手动发布一个事件:applicationContext.publishEvent()
@Component
public class MyApplicationListener implements ApplicationListener<ApplicationEvent>{
//当容器中发布此事件,方法会得到触发
@Override
public void onApplicationEvent(ApplicationEvent event) {
System.out.println("收到事件:"+event);
}
}
事件发布流程:
在refresh()方法中执行publishEvent(new ContextRefreshedEvent(this));
- 获取事件的多播器(派发器):getApplicationEventMulticaster(), 容器创建refresh()方法initAppicationEventMulticaster()初始化ApplicationEventMulticaster。
- multicastEvent派发事件
- 获取到所有的ApplicationListenr,如果有Executor,可以支持Executor进行异步派发;同步方式直接执行listener()方法,依次调用onApplicationEvent方法
@Listener注解
这个注解标在方法上spring在启动的时候就会将这个方法创建成一个监听器
@Service
public class ListenerService {
@EventListener(classes= {ApplicationEvent.class})
public void Listener(ApplicationEvent event) {
System.out.println("@EventListener收到事件:"+event);
}
}
@Listener的原理
-
@EventListener 使用EventListenerMethodProcessor处理器来解析方法上的@EventListener注解
-
EventListenerMethodProcessor实现了SmartInitializingSingleton
-
SmartInitializingSingleton 原理:
1 、ioc容器创建对象并refresh()
2 、finishBeanFactoryInitialization(beanFactory);初始化剩下的单实例bean;
先创建所有的单实例bean;再获取所有创建好的单实例bean,判断是否是SmartInitializingSingleton类型的,如果是调用afterSingletonSInstantiated();
三、获取容器底层组件(各种Aware)
自定义组件想要使用Spring容器底层的一些组件(ApplicationContext, Environment,BeanFactory等),自定义组件需要实现XXXAware接口(继承Aware接口),在创建对象的时候,Spring会调用接口规定的方法注解相关组件,把Spring底层的一些组件注入到自定义的Bean中。
@Component
public class Boss implements ApplicationContextAware, BeanNameAware, EmbeddedValueResolverAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Override
public void setBeanName(String name) {
System.out.println("bean名称:"+name);
}
@Override
public void setEmbeddedValueResolver(StringValueResolver resolver) {
String stringValue = resolver.resolveStringValue("你好${os.name},我是#{18*20}");
System.out.println(stringValue);
}
}
ApplicationContextAware 的处理器就是 ApplicationContextAwareProcessor,ApplicationContextAwareProcessor是一种BeanPostProcessor。前文提到BeanPostProcessor发生在bean初始化前后,在bean初始化之前将调用postProcessBeforeInitialization方法,ApplicationContextAwareProcessor的postProcessBeforeInitialization如下:
public 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(new PrivilegedAction<Object>() {
public Object run() {
invokeAwareInterfaces(bean);
return null;
}
}, acc);
}
else {
invokeAwareInterfaces(bean);
}
return bean;
}
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof Aware) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(
new EmbeddedValueResolver(this.applicationContext.getBeanFactory()));
}
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);
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
}
可以看出ApplicationContextAwareProcessor完成了容器中特有的一些Aware的调用,发生的时机在初bean始化之前。那么ApplicationContextAwareProcesso是何时被加入容器的?
- 容器创建时调用refresh()方法
- refresh()方法调用
prepareBeanFactory(beanFactory)方法
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//第一步,预创建bean对象
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
//第二步,调用invokeBeanFactoryPostProcessors(beanFactory)方法
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
...
//初始化bean对象实例
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
...
}
...
}
- 在
prepareBeanFactory(beanFactory)方法向容器中添加ApplicationContextAwareProcessor。
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
本文深入探讨Spring框架中BeanPostProcessor与BeanFactoryPostProcessor的使用,讲解如何通过这两种后置处理器扩展Spring容器的功能,包括在bean初始化前后执行自定义逻辑,以及在bean实例创建前对bean工厂进行操作。同时,文章还介绍了ApplicationListener的应用,用于监听容器事件,以及如何通过实现各种Aware接口获取容器底层组件。
1133

被折叠的 条评论
为什么被折叠?



