0
点赞
收藏
分享

微信扫一扫

springboot原理实战(3)-- spring扩展接口BeanPostProcessor,BeanFactoryPostProcessor


文章目录

  • ​​目录:​​
  • ​​1.BeanPostProcessor​​
  • ​​2.MyBeanFactoryPostProcessor​​
  • ​​3.BeanDefinitionRegistryPostProcessor​​
  • ​​扩展:也可以用AnnotationConfigApplicationContext注入​​

目录:

入门springboot前,先了解spring的下面这三个接口扩展,很有必要。

先看下脑图:

springboot原理实战(3)-- spring扩展接口BeanPostProcessor,BeanFactoryPostProcessor_spring

1.BeanPostProcessor

这个接口上篇文章讲过,spring利用这个接口,只要实现ApplicationContextWare接口,就可以在此接口,获取springcontext.
他的主要作用也就是:​​​在bean初始化时 搞点小动作​​​:
举例演示:
注入一个bean:

@Component
public class User {

@PostConstruct
public void init(){
System.out.println("===user init==");
}
}

实现BeanPostProcessor接口,这个接口会影响所有的bean初始化。

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("=========postProcessBeforeInitialization========"+bean.getClass());
return bean;
}

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("=========postProcessAfterInitialization========"+bean.getClass());

return bean;
}
}

测试:

public class App2 {
public static void main(String[] args) {

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.springboot.demo3");
System.out.println(User.class);
context.close();
}
}

运行结果:可以看出什么?在bean初始化前后都打印了。

springboot原理实战(3)-- spring扩展接口BeanPostProcessor,BeanFactoryPostProcessor_spring_02

2.MyBeanFactoryPostProcessor

有了bean初始化时,进行一些小动作,那么容器初始化时是不是可以做一些小动作呢?可以。
这个就是BeanFactoryPostProcessor接口。
​​​BeanFactoryPostProcessor在spring容器初始化之后触发,而且只会触发一次.​​ 我们实现下这个接口:

@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("=================="+ beanFactory.getBeanDefinitionCount());
}
}

运行结果:

springboot原理实战(3)-- spring扩展接口BeanPostProcessor,BeanFactoryPostProcessor_spring_03

显示容器预先注入了8个对象,也就是,这个spring在背后注入了其他的bean。我们就可以在​​postProcessBeanFactory()​​​方法中,在容器初始化时做一些业务操作。
特别注意: 仅仅会触发一次这个方法。

3.BeanDefinitionRegistryPostProcessor

刚才的那个方法,我们可以在容器初始化时,做一些事情,比如我们通过

​beanFactory.getBeanDefinitionCount()​​获取初始化bean的个数,但是能不能再这里注入一些bean呢?

可以的。

不过得用到BeanFactoryPostProcessor的一个子接口:

springboot原理实战(3)-- spring扩展接口BeanPostProcessor,BeanFactoryPostProcessor_spring boot_04


这个类扩展了一个方法:

springboot原理实战(3)-- spring扩展接口BeanPostProcessor,BeanFactoryPostProcessor_初始化_05


里面有个参数​​BeanDefinitionRegistry​​.这个类可以帮我们注入一些bean的操作。

springboot原理实战(3)-- spring扩展接口BeanPostProcessor,BeanFactoryPostProcessor_ide_06


通过上面的registerBeanDefinition的方法。可以注入bean。

下面的removeBeanDefinition可以移除bean。

代码演示:

我们实现这个​​BeanDefinitionRegistryPostProcessor​​接口注入10个Person对象:

public class Person {

private String name;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
}

注意Person没有加@Component。
我们用容器注入:

@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

}

@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
for (int i=1;i<=10;i++){
BeanDefinitionBuilder bdb = BeanDefinitionBuilder.rootBeanDefinition(Person.class);
bdb.addPropertyValue("name","admin"+i);
registry.registerBeanDefinition("person"+i, bdb.getBeanDefinition());
}
}

}

测试类:

public class App2 {
public static void main(String[] args) {

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.springboot.demo3");
context.getBeansOfType(Person.class).values().forEach(System.out::println);
context.close();
}
}

打印结果:

springboot原理实战(3)-- spring扩展接口BeanPostProcessor,BeanFactoryPostProcessor_初始化_07


显示注入了。

扩展:也可以用AnnotationConfigApplicationContext注入

public class App2 {
public static void main(String[] args) {

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.springboot.demo3");
for (int i=1;i<=10;i++){
BeanDefinitionBuilder bdb = BeanDefinitionBuilder.rootBeanDefinition(Person.class);
bdb.addPropertyValue("name","admin"+i);
context.registerBeanDefinition("person"+i, bdb.getBeanDefinition());
}
context.getBeansOfType(Person.class).values().forEach(System.out::println);
context.close();
}
}

运行结果:

springboot原理实战(3)-- spring扩展接口BeanPostProcessor,BeanFactoryPostProcessor_spring boot_08


为什么AnnotationConfigApplicationContext也可以注入bean呢?

springboot原理实战(3)-- spring扩展接口BeanPostProcessor,BeanFactoryPostProcessor_spring boot_09


springboot原理实战(3)-- spring扩展接口BeanPostProcessor,BeanFactoryPostProcessor_初始化_10


通过观察我们发现。​​AnnotationConfigApplicationContext​​​是​​BeanDefinitionRegistry​​​子接口的子接口。所以可以调用​​BeanDefinitionRegistry​​的所有方法!!

个人微信公号:

搜索: 怒放de每一天

不定时推送相关文章,期待和大家一起成长!!

springboot原理实战(3)-- spring扩展接口BeanPostProcessor,BeanFactoryPostProcessor_ide_11


举报

相关推荐

0 条评论