目录
执行所有postProcessBeforeInitialization方法
执行所有postProcessAfterInitialization方法
后置处理器算是实现AOP的前提,我们在这篇文章中就将会实现后置处理器,后置处理器是什么我就不介绍了,不清楚可以参考后置处理器,下面直接开始。
我们定义一个注解来标识bean的初始化方法。
- @Target(value = {ElementType.METHOD})
- @Retention(value = RetentionPolicy.RUNTIME)
- public @interface PostConstruct {
- }
我们定义一个后置处理器的接口,里面的2个方法和原生的spring是一样的。如果一个类实现了这个接口,那么这个类就是后置处理器类。
- public interface BeanPostProcessor {
- default Object postProcessBeforeInitialization(Object bean, String beanName) throws Exception {
- return bean;
- }
-
- default Object postProcessAfterInitialization(Object bean, String beanName) throws Exception {
- return bean;
- }
- }
我们创建一个方法,这个方法判断一个类是否有需要进行执行的初始化方法,也就是判断方法上有没有@PostConstruct注解
- protected void executeInitMethod(Object o) {
- for (Method method : o.getClass().getDeclaredMethods()) {
- if (method.isAnnotationPresent(PostConstruct.class)) {
- try {
- method.invoke(o);
- } catch (InvocationTargetException | IllegalAccessException e) {
- e.printStackTrace();
- }
- }
- }
- }
我们创建一个set来将后置处理器的名称存放到里面,方便后续处理
- private Set<String> beanPostProcessorNames;
-
- //代码块初始化集合
- {
- beanPostProcessorNames = new HashSet<>();
- }
我们在初始化singletonObjects集合的时候,需要对beanDefinitionMap进行遍历,我们可以在遍历的时候初始化后置处理器名称的集合,只需要判断是否实现BeanPostProcessor接口即可
- //将后置处理器的名字存储进set中
- if (bean instanceof BeanPostProcessor) {
- beanPostProcessorNames.add(name);
- }
我们需要遍历后置处理器,并且执行所有的before和after方法,所以我们可以提供2个方法,分别完成执行before和after的功能
- protected Object processorBeforeMethod(Object o, String beanName) {
- for (String postProcessorName : beanPostProcessorNames) {
- BeanPostProcessor postProcessor = (BeanPostProcessor) singletonObjects.get(postProcessorName);
- Object current = null;
- try {
- current = postProcessor.postProcessBeforeInitialization(o, beanName);
- } catch (Exception e) {
- e.printStackTrace();
- }
- if (current != null) {
- o = current;
- }
- }
- }
- protected Object processorAfterMethod(Object o, String beanName) {
- for (String postProcessorName : beanPostProcessorNames) {
- BeanPostProcessor postProcessor = (BeanPostProcessor) singletonObjects.get(postProcessorName);
- Object current = null;
- try {
- current = postProcessor.postProcessAfterInitialization(o, beanName);
- } catch (Exception e) {
- e.printStackTrace();
- }
- if (current != null) {
- o = current;
- }
- }
- return o;
- }
在上面,我们实现了初始化方法,后置处理器方法,现在我们在对象创建后进行显示调用,相当于要在2个地方进行调用,分别是解决singletonObjects依赖注入之后,如下
- //如果是自身就是后置处理器,跳过
- if (o instanceof BeanPostProcessor) continue;
-
- //后置处理器
- o = processorBeforeMethod(o, beanName);
-
- //调用init方法
- executeInitMethod(o);
-
- //后置处理器
- o = processorAfterMethod(o, beanName);
- //更新单例对象池中的对象
- singletonObjects.put(beanName, o);
然后还需要在createBean方法中进行调用。在返回之前调用即可
- //后置处理器
- o = processorBeforeMethod(o, beanName);
-
- //调用init方法
- executeInitMethod(o);
-
- //后置处理器
- o = processorAfterMethod(o, beanName);
为了方便,我们在test包下面新建2个子包,分别是bean包和processor包,bean包里面写随便写一个类,提供一个init方法。processor包下写一个类继承BeanPostProcessor接口。
- @Component
- public class Cat {
-
- @PostConstruct
- public void myInit(){
- System.out.println("这是Cat的初始化方法");
- }
- }
- @Component
- public class MyBeanPostProcessor implements BeanPostProcessor {
- @Override
- public Object postProcessBeforeInitialization(Object bean, String beanName) throws Exception {
- System.out.println(beanName+"的后置处理器--before");
- return bean;
- }
-
- @Override
- public Object postProcessAfterInitialization(Object bean, String beanName) throws Exception {
- System.out.println(beanName+"的后置处理器--after");
- return bean;
- }
- }
更改我们spring的扫描路径,也就是在更改ComponentScan注解
- @ComponentScan(path = "com.ttpfx.use.test")
- public class ComponentScanPathConfig {
- }
项目结构如下
在测试类中只需创建一个容器即可,如下
- public class MySpringTest {
-
- public static void main(String[] args) {
- ApplicationContext ioc = new ApplicationContext(ComponentScanPathConfig.class);
- }
- }
控制台输出如下
经过测试,可以发现,我们的后置处理器也没有问题。
经过这篇文章,我们已经实现了后置处理器,难度总体来说还不算特别大,在下一篇文章中我们将会实现spring的核心机制--AOP,这也是比较难的一点,我自己写的时候也调了很久的bug,做好准备,开始实现AOP吧!!!
手写spring系列
[手写spring](2)初始化BeanDefinitionMap
[手写spring](3)初始化singletonObjects,实现依赖注入