目录:
入门springboot前,先了解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初始化前后都打印了。
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()); } }
运行结果:
显示容器预先注入了8个对象,也就是,这个spring在背后注入了其他的bean。我们就可以在postProcessBeanFactory()方法中,在容器初始化时做一些业务操作。
特别注意: 仅仅会触发一次这个方法。
3.BeanDefinitionRegistryPostProcessor
刚才的那个方法,我们可以在容器初始化时,做一些事情,比如我们通过
beanFactory.getBeanDefinitionCount()获取初始化bean的个数,但是能不能再这里注入一些bean呢?
可以的。
不过得用到BeanFactoryPostProcessor的一个子接口:
这个类扩展了一个方法:
里面有个参数BeanDefinitionRegistry.这个类可以帮我们注入一些bean的操作。
通过上面的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(); } }
打印结果:
显示注入了。
扩展:也可以用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(); } }
运行结果:
为什么AnnotationConfigApplicationContext也可以注入bean呢?
通过观察我们发现。AnnotationConfigApplicationContext是BeanDefinitionRegistry子接口的子接口。所以可以调用BeanDefinitionRegistry的所有方法!!