聊聊spring中的工厂后置处理器
日期: 2021-05-06 分类: 个人收藏 522次阅读
昂,有好久没有写文章了,不知从何写起…想起之前学习过的spring源码都快忘了,后续就写一写spring源码的文章吧。今天从工厂后置处理器开头,后续的文章会引出spring是如何利用工厂后置处理器去扫描bean的。
其实我一直都喜欢读一些简短精悍的文章,因为太长了看着太累,然后就没啥兴趣了…不知大家是不是也这样呢?所以我决定写点简短没有精悍的的文章~
对spring源码有兴趣的可以关注一下。
1.BeanFactoryPostProcessor
这个是spring中工厂后置器的顶级接口,里面只提供了一个方法,先看看这个接口。
public interface BeanFactoryPostProcessor {
/**
* Modify the application context's internal bean factory after its standard
* initialization. All bean definitions will have been loaded, but no beans
* will have been instantiated yet. This allows for overriding or adding
* properties even to eager-initializing beans.
* @param beanFactory the bean factory used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
这些注释大概意思就是:提供了一个bean工厂,所有的bean都已经加载了,但是还没有实例化,这样你就在bean实例化之前为所欲为了~比如添加、修改bean的属性。
举个栗子:
这里有一个car的类,添加上它的:
@Component
public class Car {
private String name;
private Double price;
public void setName(String name) {
this.name = name;
}
public void setPrice(Double price) {
this.price = price;
}
@Override
public String toString() {
return "Car{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
}
然后自定义一个工厂后置处理器:
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition benzCarBeanDefinition = beanFactory.getBeanDefinition("car");
//属性
MutablePropertyValues propertyValues = benzCarBeanDefinition.getPropertyValues();
//会调用bean中的set方法
propertyValues.add("name","奔驰c200l");
propertyValues.add("price",300000.00);
}
}
需要写一个配置类,定义需要扫描的包:
@Configuration
@ComponentScan("test")
public class MyConfiguration {
}
然后写一个测试类:
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfiguration.class);
Car car = (Car) context.getBean("car");
System.out.println(car);
//输出 Car{name='奔驰c200l', price=300000.0}
}
}
最后的输出中,car的name 和 price都被赋予了值。
2.BeanDefinitionRegistryPostProcessor
这个接口继承了上面的BeanFactoryPostProcessor,是BeanFactoryPostProcessor的扩展,看看这个接口:
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
/**
* Modify the application context's internal bean definition registry after its
* standard initialization. All regular bean definitions will have been loaded,
* but no beans will have been instantiated yet. This allows for adding further
* bean definitions before the next post-processing phase kicks in.
* @param registry the bean definition registry used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
这个接口的方法,提供了一个registry的参数,这是一个注册器,可以用这个注册器搞一些注册的事情,动态去注册bean。
再举个栗子:
自定义一个BeanDefinitionRegistryPostProcessor:
@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
/**
* 扩展的方法:提供了一个注册器,可以动态的去注册bean
* @param registry the bean definition registry used by the application context
* @throws BeansException
*/
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
for (int i = 0; i < 10; i++) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(Car.class);
builder.addPropertyValue("name", "奔驰_" + i);
registry.registerBeanDefinition("car" + i, builder.getBeanDefinition());
}
System.out.println("动态注入bean完成");
}
/**
* 父类中的方法 #postProcessBeanFactory 可以修改、设置 bean的属性
* @param beanFactory the bean factory used by the application context
* @throws BeansException
*/
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
}
然后写一个测试类,看看是不是往spring容器中注入了10个car?
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfiguration.class);
Map<String, Car> beansOfType = context.getBeansOfType(Car.class);
beansOfType.forEach((k,v)->{
System.out.println(k+">>>"+v.toString());
});
}
}
最后看到spring容器中已经有了10个car的bean的实例了。
这篇文章对spring的工厂后置处理器简单的介绍了一下,因为spring中使用了工厂后置处理器对整个spring工程进行了扫描,对bean的解析,一些注解的处理,个人感觉工厂后置处理器是spring源码阅读必须知道的东西,比较重要。
下期文章,会讲spring是如何利用工厂后置处理器对整个工程进行扫描的,感兴趣的可以关注一下~也可以微信搜索「山主」,第一时间阅读最新文章。
除特别声明,本站所有文章均为原创,如需转载请以超级链接形式注明出处:SmartCat's Blog
精华推荐