一、BeanPostProcessor 主要用来对已经实例化的BEAN进行再次处理和修改,返回新定义的对象。
1.例如当CONTROLLER使用@RESOURCE注入SERVICE对象时,SPRING容器创建的是原始的BEAN类对象,而AbstractAutowireCapableBeanFactory则会将此对象转换为cglib,或者JDK的代理对象,并插入各种AOP拦截器。
二、BeanFactoryPostProcessor主要用来对工厂内部的beanDefinitionMap中的BEAN定义的属性进行各种修改和填充。
1.例如类中属性使用配置文件的定义来自动填充时,使PropertySourcesPlaceholderConfigurer会自动读取配置文件,并且填充到BEANDEFINE的属性中。
<context:property-placeholder location="conf.properties"/> <alias name="people1" alias="p1"></alias> <bean id="people1" class="com.tpw.newday.bean.PeopleBean"> <property name="name" value="${p1.name}"/> </bean>
三、PropertySourcesPlaceholderConfigurer加载原理分析
1.示例配置
@ImportResource({"classpath:spring/spring-provider.xml"})
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<dubbo:application name="${mydubbo.application.name}"/>
<dubbo:registry id="nacos1" protocol="nacos" address="${nacos.address}" group="${mydubbo.registry.group}"/>
<dubbo:protocol name="dubbo" port="20880" threadpool="cached" />
<dubbo:service interface="com.example.demo3.DemoService" ref="demoServiceImpl" registry="nacos1"/>
<bean id="myDubboCfg"
class="com.example.demo3.config.DubboCfg">
<property name="applicationName" value="${mydubbo.application.name}" />
<property name="nacosAddress" value="${nacos.address}" />
<property name="registryGroupName" value="${mydubbo.registry.group}"/>
<property name="multicastAddress" value="${mydubbo.multicast.address}" />
</bean>
<!--<dubbo:consumer filter="consumerTraceLogFilter" />
<bean id="traceLogInterceptor" class="com.clife.logger.adapter.remote.springmvc.TraceLogInterceptor"/>
<context:component-scan base-package="com.clife.logger.adapter.aop" />
<context:component-scan base-package="com.clife.logger.adapter.support.reload" />
<aop:aspectj-autoproxy proxy-target-class="true"/>-->
<!-- <import resource="classpath:spring/consumer/*-consumer.xml"/>-->
<!-- <!–公共平台服务订阅–>-->
<!-- <import resource="classpath:spring/remote-service-consumer.xml"/>-->
</beans>
2.ConfigurationClassPostProcessor处理ImportResource注解,接着会调用
XmlBeanDefinitionReader.loadBeanDefinitions(String location)
3.调用DefaultBeanDefinitionDocumentReader.parseBeanDefinitions逐个解析XML节点
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate);
}
else {
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
4.接下来进行BEAN中的属性变量替换为spring容器的Enviorment中的PropertySource中存在的变量,调用 到PropertySourcesPlaceholderConfigurer.postProcessBeanFactory。
替换前
5.对BeanDefine对象进行属性对象处理。
BeanDefinitionVisitor
protected Object resolveValue(@Nullable Object value) {
if (value instanceof BeanDefinition) {
visitBeanDefinition((BeanDefinition) value);
}
else if (value instanceof BeanDefinitionHolder) {
visitBeanDefinition(((BeanDefinitionHolder) value).getBeanDefinition());
}
else if (value instanceof RuntimeBeanReference) {
RuntimeBeanReference ref = (RuntimeBeanReference) value;
String newBeanName = resolveStringValue(ref.getBeanName());
if (newBeanName == null) {
return null;
}
if (!newBeanName.equals(ref.getBeanName())) {
return new RuntimeBeanReference(newBeanName);
}
}
else if (value instanceof RuntimeBeanNameReference) {
RuntimeBeanNameReference ref = (RuntimeBeanNameReference) value;
String newBeanName = resolveStringValue(ref.getBeanName());
if (newBeanName == null) {
return null;
}
if (!newBeanName.equals(ref.getBeanName())) {
return new RuntimeBeanNameReference(newBeanName);
}
}
else if (value instanceof Object[]) {
visitArray((Object[]) value);
}
else if (value instanceof List) {
visitList((List) value);
}
else if (value instanceof Set) {
visitSet((Set) value);
}
else if (value instanceof Map) {
visitMap((Map) value);
}
else if (value instanceof TypedStringValue) {
TypedStringValue typedStringValue = (TypedStringValue) value;
String stringValue = typedStringValue.getValue();
if (stringValue != null) {
String visitedString = resolveStringValue(stringValue);
typedStringValue.setValue(visitedString);
}
}
else if (value instanceof String) {
return resolveStringValue((String) value);
}
return value;
}
6.进行真正的变量替换
7.替换后
四、@autowired,@Value加载原理分析
1.AutowiredAnnotationBeanPostProcessor处理类的postProcessMergedBeanDefinition
在AbstractAutowireCapableBeanFactory.doCreateBean后触发,这里会将@autowired反射获取到对象属性的描述符映射元数据进行保存。
2.
AutowiredAnnotationBeanPostProcessor处理类的postProcessProperties
在AbstractAutowireCapableBeanFactory.populateBean-》
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
后触发,这里会将@autowired反射获取到对象属性的描述符映射元数据进行保存。