spring BeanPostProcessor,BeanFactoryPostProcessor作用

一、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"/>-->
<!--    &lt;!&ndash;公共平台服务订阅&ndash;&gt;-->
<!--    <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反射获取到对象属性的描述符映射元数据进行保存。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值