看这篇文章之前,需要了解Bean创建的过程,本篇文章是接着bean创建的基本流程的续写
Bean创建的基本过程:http://t.csdn.cn/1lK2d
(熟悉Bean创建的基本流程是前提)
Spring的后处理器是Spring对外开发的重要扩展点,允许我们介入到Bean的整个实例化流程中来,以达到动态注册BeanDefinition,动态修改BeanDefinition,以及动态修改Bean的作用。Spring主要有两种后处理器:
那Spring的后置处理器有什么用处呢?
不知道你看到它可以动态注册BeanDefinition时有什么想法,对,你想的没错,注解开发原理中就是用Spring的后置处理器来动态创建Bean对象的,别眨眼,接下来就时见证奇迹的时刻
Bean工厂后处理器,在BeanDefinitionMap填充完毕,Bean实例化之前执行;也就是当把xml中所有bean配置信息封装成BeanDefinition对象,装到BeanDefinitionMap集合后,但还没有反射创建bean对象时,再往map中注册BeanDefinition对象,后续反射就会创建出新的xml中未定义的对象
Bean工厂后处理器 – BeanFactoryPostProcessor
BeanFactoryPostProcessor是一个接口规范,实现了该接口的类只要交由Spring容器管理的话,在BeanDefinitionMap填充完毕后,Spring就会回调该接口的方法,用于对BeanDefinition注册和修改的功能。
所以它的使用分以下几步
使用方式如下
由于BeanDefinition是接口,我们要new 一个BeanDefinition对象,就要new 它的一个实现类RootBeanDefinition对象
其中需要强转为DefaultListableBeanFactory是因为,ConfigurableListableBeanFactory的对象无法把beanDefinition注册到map中,BeanDefinitionMap是DefaultListableBeanFactory中定义的集合,而DefaultListableBeanFactory又是实现了ConfigurableListableBeanFactory的接口,所以强转一下。
不得不说,这个源码自己也需要多看,不然这些接口名类名是什么,继承了什么,有什么关键成员变量都不清楚,看这些调用关系自然就云里雾里
Spring 提供了一个BeanFactoryPostProcessor的子接口BeanDefinitionRegistryPostProcessor专门用于注册BeanDefinition操作
public class MyBeanFactoryPostProcessor2 implements BeanDefinitionRegistryPostProcessor {
//这个方法是BeanFactoryPostProcessor接口的方法,重写一下就不用管了
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
BeanDefinition beanDefinition = new RootBeanDefinition();
beanDefinition.setBeanClassName("com.dao.UserDaoImpl");//要创建的bean的位置
//注册beanDefinition
beanDefinitionRegistry.registerBeanDefinition("userDao",beanDefinition);
}
}
最后main方法中调用时
UserDao userDao = applicationContext.getBean(UserDao.class)
Bean后处理器 – BeanPostProcessor
Bean被实例化后,到最终缓存到名为singletonObjects单例池之前,中间会经过Bean的初始化过程,例如:属性的填充、初始方法init的执行等,其中有一个对外进行扩展的点BeanPostProcessor,我们称为Bean后处理。跟上面的Bean工厂后处理器相似,它也是一个接口,实现了该接口并被容器管理的BeanPostProcessor,会在流程节点上被Spring自动调用。
bean后处理器的使用步骤和bean工厂后处理器基本类似,只是处理时机不一样,bean工厂后处理器在填充map后,实例化前;bean后处理器在实例化后,添加单例池前
BeanPostProcessor的接口定义如下(模板):
public interface BeanPostProcessor {
@Nullable//表示该方法可以不写
//在属性注入完毕,init初始化方法执行之前被回调
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Nullable
//在初始化方法执行之后,被添加到单例池singletonObjects之前被回调
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
原理大概就是用包扫描工具类,指定包及其子包下的类上加了自定义注解的类名获取并添加到一个map集合中,然后遍历依次对它们进行包装成一个个BeanDefinition对象,然后再它们注册到BeanDefinitionMap集合中,后续反射创建bean时,这些注解添加的bean也会被创建。
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
//指定要扫描的包
String basePackage = "com";
//调用扫描工具BaseClassScanUtils扫描指定包及其子包下的@MyComponent
Map<String, Class> myComponentClassMap = BaseClassScanUtils.scanMyComponentAnnotation(basePackage);
//遍历Map集合,创建BeanDefinition对象进行注册
myComponentClassMap.forEach((beanName,clazz)->{
try {
BeanDefinition beanDefinition = new RootBeanDefinition();
beanDefinition.setBeanClassName(clazz.getName());
registry.registerBeanDefinition(beanName,beanDefinition);
} catch (Exception e) {
e.printStackTrace();
}
});}
不得不说有那味了