SpringBean的实例化过程
我们都知道,当我们把bean交给Spring容器进行管理,也就是在xml文件中配置bean,当我们需要用到某个bean时,Spring就帮我们创建好对象使用。那我们来了解一下这中间的过程是怎样的。
1.在xml中配置bean,工厂将一整个语句配置信息转换成beanDefinition对象。注意是整条配置语句的信息,而不是某个bean。
2.beanDefinition对象然后被存储在一个叫beanDefinitionMap的Map集合中。
3.Spring框架遍历该Map集合,使用反射创建Bean实例对象,创建好后,将对象存储在单例池(singletonObjects)的Map集合中。
4.当调用getBean方法时,就从最后的Map集合中取出对象。
Spring后处理器
在原本Spring给我们一个已经比较完整的框架结构后,但是我们想让它实现某个不一样的功能时,Spring后处理器允许我们介入Bean的整个实例化过程中来进行动态注册BeanDefinition,动态修改BeanDefinition以及动态修改Bean等操作。后处理器包括以下两种,它们的区别在于作用时间段不同:
1,BeanFactoryPostProcessor:Bean工厂后处理器,它执行是在BeanDefinitionMap填充完毕,进行遍历之前。
2,BeanPostProcessor:Bean后处理器,它执行在Bean实例化后,填充到单例池之前。
1 Spring工厂后处理器
即BeanFactoryPostProcessor,它实际上是一个接口,内部提供了一个方法,只要将实现该接口的实现类交给Spring容器管理,Spring就会帮我们在它的作用时机时调用实现方法。
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("填充好BeanDefinitionMap后执行该方法");
}
}
这个接口方法可以完成动态注册/修改BeanDefinition。
什么是动态注册Beandefinition?
可以理解为BeanDefinition对象装填到BeanDefinitionMap集合中的这一个过程。
先看动态修改BeanDefinition:
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("填充好BeanDefinitionMap后执行该方法");
//修改beanDefinition
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("Service");
//将Service的权限名强制改为UserDao的
beanDefinition.setBeanClassName("com.demo.impl.UserDaoImpl");
}
}
来看控制台输出的是什么:
可以看到,原本应该输出ServiceImpl实例对象,结果却转换成了UserDaoImpl。
在刚开始输出时,报错转换错误。我们在getbean时不要进行强转,就Object就好。
再看动态注册beanDefinition:
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("填充好BeanDefinitionMap后执行该方法");
//注册BeanDefinition
//创建beanDefinition
BeanDefinition beanDefinition=new RootBeanDefinition("com.demo.impl.PersonDaoImpl");
//转换一下才能调用下述方法->registerBeanDefinition
DefaultListableBeanFactory defaultListableBeanFactory= (DefaultListableBeanFactory) beanFactory;
//注册关键一步,相当于把创建的beanDefinition装在Map中
defaultListableBeanFactory.registerBeanDefinition("personDao",beanDefinition);
}
}
在这里,我并没有在xml中配置PersonDao的相关信息,但是也可以获得它的实例对象,这就是BeanFactoryPostProcessor帮我们做到的。
暂时先写这么多,明天继续>W<!
-------------------这是分割线------------------------
继续写完捏:
优化:
在上面,当我们想要调用注册方法时,还得强制转化一下beanFactory,不太方便,所以就有了另外一个类帮助直接调用。BeanDefinitionRegistryPostProcessor,它是BeanFactoryPostProcessor的子类。看下源码:
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
default void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
}
它的使用方法如下:
public class MyBeanDefinitionRegistryPostProcessor implements org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
// 创建beanDefinition
BeanDefinition beanDefinition=new RootBeanDefinition("com.demo.impl.PersonDaoImpl");
//注册关键一步,相当于把创建的beanDefinition装在Map中
registry.registerBeanDefinition("personDao",beanDefinition);
}
}
总的流程图:
2 Spring后处理器
BeanPostProcessor,其实基本跟beanFactoryPostProcessor实现差不多。它里面实现两个不同时机执行的方法:
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println(bean+"postProcessBeforeInitialization方法");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println(bean+"postProcessAfterInitialization方法");
return bean;
}
}
结合到bean的实例化过程中,来看下面几个方法它执行时机
首先完善一下我们的ServiceImpl。
public class ServiceImpl implements Service,InitializingBean{
private int num;
public void setNum(int num) {
this.num = num;
}
public ServiceImpl() {
System.out.println("bean实例化");
}
public void init(){
System.out.println("自定义初始化方法执行");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean方法执行");
}
}
然后xml配置
<bean id="Service" class="com.demo.impl.ServiceImpl" init-method="init">
<property name="num" value="111"></property>
</bean>
然后看输出:
是不是就一目了然它们的执行先后顺序了呢。
标签:throws,Spring,void,bean,SpringBean,及后,处理器,public,beanDefinition From: https://blog.csdn.net/Ggjvhsjsj/article/details/143245986