如果希望在Spring容器完成实例化、配置和初始化bean之后实现某些自定义逻辑, 则可以实现一个或多个 BeanPostProcessor 接口。BeanPostProcessor中有两个抽象方法:
/**
* 后置处理器:初始化前后进行处理工作
*/
@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();
}
}
设置数值越小优先级越高.
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实例还未创建是执行;
@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);
}
}
原理:
监听容器发布的事件,实现一个监听器的步骤:
@Component
public class MyApplicationListener implements ApplicationListener<ApplicationEvent>{
//当容器中发布此事件,方法会得到触发
@Override
public void onApplicationEvent(ApplicationEvent event) {
System.out.println("收到事件:"+event);
}
}
事件发布流程:
在refresh()方法中执行publishEvent(new ContextRefreshedEvent(this));
@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();
自定义组件想要使用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是何时被加入容器的?
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));