【spring源码】五、工厂后置处理器BeanFactoryPostProcessor【重要】

本文深入探讨Spring工厂后置处理器,介绍其基础知识,包括BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor的作用。通过测试代码展示不同方式注册工厂后置处理器,观察bd map变化和执行时机。还对ConfigurationClassPostProcessor进行解读,分析AOP注解时机及整合源码的方法,最后探讨AnnotatedBeanDefinitionReader的作用和应用场景。

本文地址https://blog.youkuaiyun.com/hancoder/article/details/111413351

说明,本文参考了子路老师博客https://blog.youkuaiyun.com/java_lyvee/category_7351027.html,但自己也看过很多这方面的视频,包括尚硅谷的注解驱动开发,所以加了些自己的说明,尽量简洁。个人认为此文是我近期写的最好的一篇了,我感觉快要打通ssm源码整合了。

按理说工厂后置处理器没有getBean重点,但是我读了那么久源码迟迟有些地方不懂,就是因为当初没有读好工厂的后置处理器,一直没有搞懂注解的注册时机,再加上尚硅谷讲的@EnableAspectJAutoProxy也没说好到底怎么个注册法,看了几遍才发现是工厂后置处理器的问题。故写了此文

正在更新spring源码系统文章:

一、工厂后置处理器基础知识

工厂后置处理器的作用是新增和修改bean定义的,而spring中有两个接口与工厂后置处理器有关,分别是BeanFactoryPostProcessorBeanDefinitionRegistryPostProcessor

  • BeanFactoryPostProcessor:需要实现一个方法。只能修改bean定义
  • BeanDefinitionRegistryPostProcessor:他本身有一个需要实现方法,但因为继承了上面的BeanFactoryPostProcessor接口,所以需要实现2个方法。分别是修改和添加bean定义

在实际开发中用的比较少,但各个框架源码整合中用的比较多,这里我们就不写用法了,直接看helloworld吧。

二、测试代码

bean定义:bean Definition,我们简称bd,存放bd的map我们简写为bd map,不懂bd的可以取前文看

1 工厂后置处理器

我们首先需要了解他们的用法,如下,我分别为每个接口创建了个实现类,只做了简单打印,用来看看他当时里面有什么bean定义,并用注解@Component将他们加到spring容器中。

1.1 注解的:

这里是意思是定义BeanFactoryPostProcessor的实现类,并且在上面@Component。然后在里面的postProcessBeanFactory()方法里打印当前有多少个bd

@Component
public class MyFacPostProcess_zhujie  // 后面有_zhujie的标识
    implements BeanFactoryPostProcessor {
   
   
    
	@Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
   
   
		System.out.println("===注解的MyFacPostProcess.postProcessBeanFactory()被执行。。。");
		int count = beanFactory.getBeanDefinitionCount();//bean定义的数量
		String[] names = beanFactory.getBeanDefinitionNames();//bean定义的名字
		System.out.println("当前BeanFactory中有"+count+" 个Bean");
		System.out.println(Arrays.asList(names));
	}
}

和上面的逻辑一样,定义BeanDefinitionRegistryPostProcessor的实现类,并@Component。他们都是后置处理器,只不过BeanDefinitionRegistryPostProcessor可以新增和修改bd,而上面的BeanFactoryPostProcessor只能修改bd。

所以我们在它的新增bd方法里尝试new bd并设置class,然后用registry注册器注册到容器中

@Component
public class MyBeanDefinitionRegistryPostProcessor_zhujie 
    implements BeanDefinitionRegistryPostProcessor {
   
   

    @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
   
   
        System.out.println("===注解的MyBeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry()执行。。。");
        int count = registry.getBeanDefinitionCount();//bean定义的数量
        String[] names = registry.getBeanDefinitionNames();//bean定义的名字
        System.out.println("当前BeanFactory中有"+count+" 个Bean");
        System.out.println(Arrays.asList(names));


        // 新增bd
        GenericBeanDefinition genericBeanDefinition =
            new GenericBeanDefinition() ;
        genericBeanDefinition.setBeanClass(Yellow.class);
        registry.registerBeanDefinition("yellow1",genericBeanDefinition);

    }

    @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
   
   
        System.out.println("===注解的MyBeanDefinitionRegistryPostProcessor.postProcessBeanFactory()执行。。。");
        int count = beanFactory.getBeanDefinitionCount();//bean定义的数量
        String[] names = beanFactory.getBeanDefinitionNames();//bean定义的名字
        System.out.println("当前BeanFactory中有"+count+" 个Bean");
        System.out.println(Arrays.asList(names));
    }
}
1.2 通过ac.addBeanFactoryPostProcessor添加的实体bean

这里的意思是我们又定义了上面两个接口的实现类,只不过没加@Component,一会再手动注册

注意不要加@Component注解,我们要手动注册工厂后置处理器。而且我们传入ac的时候已经是实例化好的

public class RuCanBeanDefinitionRegistryPostProcessor  // rucan的意思是说一会要手动注册
    implements BeanDefinitionRegistryPostProcessor {
   
   
    
	@Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
   
   
		System.out.println("===入参的registry.postProcessBeanDefinitionRegistry()执行。。。");
	}

	@Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
   
   
		System.out.println("===入参的registry.postProcessBeanDefinitionRegistry()执行。。。");
	}
}
public class RuCanBeanFactoryPostProcessor 
    implements BeanFactoryPostProcessor {
   
   

	@Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
   
   
		System.out.println("===入参的普通factoryPostPro.postProcessBeanDefinitionRegistry()执行。。。");
	}
}
1.3 通过ac.registerBeanDefinition添加的bd

(下面这两个类不用太在意,其实是我前期没学好弄的,但加上也无所谓,我们就能判断ac.addBeanFactoryPostProcessor和ac.registerBeanDefinition的区别了)

public class MyFacPostProcess_ShouDongZhuRu 
    implements BeanFactoryPostProcessor{
   
   

    @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
   
   
        System.out.println("===手动注入的MyFacPostProcess.postProcessBeanFactory()被执行。。。");
        int count = beanFactory.getBeanDefinitionCount();//bean定义的数量
        String[] names = beanFactory.getBeanDefinitionNames();//bean定义的名字
        System.out.println("当前BeanFactory中有"+count+" 个Bean");
        System.out.println(Arrays.asList(names));
    }
}
public class MyBeanDefinitionRegistryPostProcessor_ShouDongZhuRu 
    implements BeanDefinitionRegistryPostProcessor{
   
   

    @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
   
   
        System.out.println("===手动注入的MyBeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry()执行。。。");
        int count = registry.getBeanDefinitionCount();//bean定义的数量
        String[] names = registry.getBeanDefinitionNames();//bean定义的名字
        System.out.println("当前BeanFactory中有"+count+" 个Bean");
        System.out.println(Arrays.asList(names));
        GenericBeanDefinition genericBeanDefinition =
            new GenericBeanDefinition() ;
        genericBeanDefinition.setBeanClass(Blue.class);
        registry.registerBeanDefinition("bule1",genericBeanDefinition);
    }

    @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
   
   
        System.out.println("===手动注入的MyBeanDefinitionRegistryPostProcessor.postProcessBeanFactory()执行。。。");
        int count = beanFactory.getBeanDefinitionCount();//bean定义的数量
        String[] names = beanFactory.getBeanDefinitionNames();//bean定义的名字
        System.out.println("当前BeanFactory中有"+count+" 个Bean");
        System.out.println(Arrays.asList(names));
    }

}

2 配置类

为了能扫描到上面的注解,我们定义配置类并扫描,此外在里面@Bean一个普通的car对象

@Configuration // 告诉Spring这是一个配置类
@ComponentScan(value="com.atguigu")
public class MainConfigFacPostProcesser {
   
   

	// 简单注入一个bean,观察执行时机
	@Bean
	Car Car1(){
   
   
		return new Car();
	}
}

3 启动类的改写

我们的启动类一般的写法是new AnnotationConfigApplicationContext(Config.class)这样子,但我们看一下他源码

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
   
   
    this();
    register(componentClasses);
    refresh();
}

他分为了三个步骤,为了后续解释的需要,我们给他们分开写。另外我们应该意识到,在下面加注释就是在上面加注释,执行时机都是一样的。我们加了6个关键点,为了观察工厂的状态

  • 比较ac.registerBeanDefinition和ac.addBeanFactoryPostProcessor方法的区别
public class MainTest1 {
   
   

	public static void main(String[] args) {
   
   
		// 1 去初始化工厂
		// 打断点。下面这句就是创建了一个空工厂
		AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值