实战:
1、spring在bean初始化前中后需要加代码怎么办?
看这里:自定义MyPostProcessor类,并实现BeanPostProcessor接口,并重写postProcessBeforeInitialization方法和postProcessAfterInitialization方法即可实现,在bean装在前和装在后干一些小动作。在bean初始化中的时候干一些小动作就要在bean配置的xml文件的bean节点中配置对应的init-method="myInit"方法
看下边:
public class MyPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
System.out.println("对象" + beanName + "初始化前干的小动作");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
System.out.println("对象" + beanName + "初试化完成后干的小动作");
return bean;
}
}
<bean id="MyBean" class="xxx.MyBean" init-method="myInit"></bean>
配置了之后,在初始化的时候会执行TestBean中定义的myInit方法。
IOC原理:
1、(定位)现根据配置的bean文件的路径找到文件,并解析为document对象
2、(加载)下边开始解析具体的解析过程由 BeanDefinitionParserDelegate 实现BeanDefinitionParserDelegate 中定义了 Spring Bean 定义 XML 文件的各种元素具体的解析方法parseBeanDefinitions
3、(注册)是由DefaultListableBeanFactory类的registerBeanDefinition(String beanName, BeanDefinition beanDefinition)方法注册到IOC容器里的。、
IOC容器就是一个map,key是beanName,value是Document解析成的BeanDefinition(BeanDefinition里存放了bean所有的定义信息)
/** Map of bean definition objects, keyed by bean name */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
至此已经完成了IOC容器的初始化工作,bean的实例化是发生在注入阶段。
小结:
补充:以XML配置为例
1、根据application.xml文件定位到bean配置文件
2、AbstractApplicationContext的refresh()方法定义了bean定义(bean.xml文件)载入流程
3、refresh()方法中的obtainFreshBeanFactory()方法具体的启动容器载入bean配置信息
4、AbstractRefreshableApplicationContext中的refreshBeanFactory()方法先判断如果有容器存在则先销毁容器中的bean并关闭容器,然后再调用createBeanFactory(); 创建IOC容器,然后调用loadBeanDefinitions(beanFactory);方法加载bean定义文件
5、AbstractXmlApplicationContext中的loadBeanDefinitions(beanFactory);方法就是具体的载入bean定义的方法。
6、以Xml配置为例会调用AbstractBeanDefinitionReader类中的loadBeanDefinitions()方法加载bean定义资源。
7、具体的读取bean定义资源文件的是在XmlBeanDefinitionReader类中的doLoadBeanDefinitions()方法,最终会将bean定义资源文件转换成一个Document对象
下边开始加载解析出来的document对象的bean定义文件
8、XmlBeanDefinitionReader类中的registerBeanDefinitions()方法最终会调用DefaultBeanDefinitionDocumentReader类种的
doRegisterBeanDefinitions(Element root)方法去解析。真正解析bean配置资源标签的是parseBeanDefinitions()方法,最终将解析好的数据放在springIOC所认识的数据结构BeanDefinition对象里边。
9、将解析好的BeanDefinition向容器中注册:DefaultListableBeanFactory类中的 registerBeanDefinition(String beanName, BeanDefinition beanDefinition)方法就是注册的具体方法:最终会把BeanDefinition通过
synchronized (this.beanDefinitionMap) { this.beanDefinitionMap.put(beanName, beanDefinition);的方式将beanName和BeanDefinition放在一个ConcurrentHashMap中。
至此IOC容器已经初始化完毕,在IOC容器中已经建立了整个bean的配置信息,IOC 容器的作用就是对这些注册的 Bean 定义信 息进行处理和维护。