文章目录
- 一、目标:给代理对象的属性设置值
- 二、设计:给代理对象的属性设置值
- 三、实现:给代理对象的属性设置值
- 3.1 工程结构
- 3.2 在Bean生命周期中创建代理对象类图
- 3.3 判断CGLIB对象
- 3.4 迁移创建AOP代理方法
- 3.4.1 实例化感知对象处理
- 3.4.2 扫描自定义注解类
- 3.4.3 默认自动代理创建者
- 3.5 在Bean生命周期中初始化执行
- 四、测试:给代理对象的属性设置值
- 4.1 添加测试配置
- 4.1.1 用户服务层实现类
- 4.1.2 用户前置处理
- 4.1.3 Spring属性配置文件
- 4.2 单元测试
- 五、总结:给代理对象的属性设置值
一、目标:给代理对象的属性设置值
💡 如何给代理对象中的属性填充相应的值?
- 因为在之前把 AOP 动态代理,融入到 Bean 的生命周期时,创建代理对象是在整个创建 Bean 对象之前,也就是这个代理对象的创建并不是在 Bean 生命周期中。
- 所以我们要把代理对象的创建融入到 Bean 的生命周期中,也就是需要把创建代理对象的逻辑迁移到 Bean 对象执行初始化方法之后,再执行代理对象的创建。
二、设计:给代理对象的属性设置值
💡 设计:把创建代理对象的逻辑迁移到对象执行初始化之后。
- 创建代理对象:
DefaultAdvisorAutoProxyCreator
实现的InstantiationAwareBeanPostProcessor
接口。 - 那么原本在
Before
中的操作,则需要放到After
中处理
- 在创建 Bean 对象
createBean
的生命周期中,有一个阶段是在 Bean 对象属性填充完成以后,执行 Bean 的初始化方法和BeanPostProcessor
的前置和后置处理。- 例如:感知
Aware
对象、处理init-method
方法等。
- 例如:感知
- 那么在这个阶段的
BeanPostProcessor After
就可以用于创建处理对象操作。 - 在
DefaultAdvisorAutoProxyCreator
用于创建代理对象的操作中,需要把创建操作从postProcessBeforeInstantiation
方法中迁移到postProcessAfterInitialization
,这样才能满足 Bean 属性填充后的创建操作。
三、实现:给代理对象的属性设置值
3.1 工程结构
spring-step-15
|-src|-main| |-java| |-com.lino.springframework| |-aop| | |-aspectj| | | |-AspectJExpressionPointcut.java| | | |-AspectJExpressionPointcutAdvisor.java| | |-framework| | | |-adapter| | | | |-MethodBeforeAdviceInterceptor.java| | | |-autoproxy| | | | |-DefaultAdvisorAutoProxyCreator.java| | | |-AopProxy.java| | | |-Cglib2AopProxy.java| | | |-JdkDynamicAopProxy.java| | | |-ProxyFactory.java| | | |-ReflectiveMethodInvocation.java| | |-AdvisedSupport.java| | |-Advisor.java| | |-BeforeAdvice.java| | |-ClassFilter.java| | |-MethodBeforeAdvice.java| | |-MethodMatcher.java| | |-Pointcut.java| | |-PointcutAdvisor.java| | |-TargetSource.java| |-beans| | |-factory| | | |-annotation| | | | |-Autowired.java| | | | |-AutowiredAnnotationBeanPostProcessor.java| | | | |-Qualifier.java| | | | |-Value.java| | | |-config| | | | |-AutowireCapableBeanFactory.java| | | | |-BeanDefinition.java| | | | |-BeanFactoryPostProcessor.java| | | | |-BeanPostProcessor.java| | | | |-BeanReference.java| | | | |-ConfigurableBeanFactory.java| | | | |-InstantiationAwareBeanPostProcessor.java| | | | |-SingletonBeanRegistry.java| | | |-support| | | | |-AbstractAutowireCapableBeanFactory.java| | | | |-AbstractBeabDefinitionReader.java| | | | |-AbstractBeabFactory.java| | | | |-BeabDefinitionReader.java| | | | |-BeanDefinitionRegistry.java| | | | |-CglibSubclassingInstantiationStrategy.java| | | | |-DefaultListableBeanFactory.java| | | | |-DefaultSingletonBeanRegistry.java| | | | |-DisposableBeanAdapter.java| | | | |-FactoryBeanRegistrySupport.java| | | | |-InstantiationStrategy.java| | | | |-SimpleInstantiationStrategy.java| | | |-xml| | | | |-XmlBeanDefinitionReader.java| | | |-Aware.java| | | |-BeanClassLoaderAware.java| | | |-BeanFactory.java| | | |-BeanFactoryAware.java| | | |-BeanNameAware.java| | | |-ConfigurableListableBeanFactory.java| | | |-DisposableBean.java| | | |-FactoryBean.java| | | |-HierarcgicalBeanFactory.java| | | |-InitializingBean.java| | | |-ListableBeanFactory.java| | | |-PropertyPlaceholderConfigurer.java| | |-BeansException.java| | |-PropertyValue.java| | |-PropertyValues.java| |-context| | |-annotation| | | |-ClassPathBeanDefinitionScanner.java| | | |-ClassPathScanningCandidateComponentProvider.java| | | |-Scope.java| | |-event| | | |-AbstractApplicationEventMulticaster.java| | | |-ApplicationContextEvent.java| | | |-ApplicationEventMulticaster.java| | | |-ContextclosedEvent.java| | | |-ContextRefreshedEvent.java| | | |-SimpleApplicationEventMulticaster.java| | |-support| | | |-AbstractApplicationContext.java| | | |-AbstractRefreshableApplicationContext.java| | | |-AbstractXmlApplicationContext.java| | | |-ApplicationContextAwareProcessor.java| | | |-ClassPathXmlApplicationContext.java| | |-ApplicationContext.java| | |-ApplicationContextAware.java| | |-ApplicationEvent.java| | |-ApplicationEventPublisher.java| | |-ApplicationListener.java| | |-ConfigurableApplicationContext.java| |-core.io| | |-ClassPathResource.java| | |-DefaultResourceLoader.java| | |-FileSystemResource.java| | |-Resource.java| | |-ResourceLoader.java| | |-UrlResource.java| |-stereotype| | |-Component.java| |-util| | |-ClassUtils.java| | |-StringValueResolver.java|-test|-java|-com.lino.springframework.test|-bean| |-IUserService.java| |-UserService.java| |-UserServiceBeforeAdvice.java|-ApiTest.java|-resources|-spring.xml|-token.properties
3.2 在Bean生命周期中创建代理对象类图
- 本节完成关于代理对象中属性的填充问题,但实际解决的思路是处理在 Bean 生命周期中合适的位置(
初始化 initializeBean
)中处理代理类的创建。 - 主要包括:
DefaultAdvisorAutoProxyCreator
类创建代理对象的操作放置在postProcessAfterInitialization
方法中。- 在
AbstractAutowireCapableBeanFactory
完成初始化方法的调用操作。
- 注意:在目前的 Spring 框架中,
AbstractAutowireCapableBeanFactory
类里使用的是CglibSubclassingInstantiationStrategy
创建对象,所有有需要判断对象获取接口的方法中,也都需要判断是否为 CGLIB 创建,否则是不能正确获取到接口的。- 如:
ClassUtils.isCglibProxyClass(clazz) ? clazz.getSuperclass() : clazz
- 如:
3.3 判断CGLIB对象
TargetSource.java
package com.lino.springframework.aop;import com.lino.springframework.util.ClassUtils;/*** @description: 被代理的目标对象*/
public class TargetSource {private final Object target;public TargetSource(Object target) {this.target = target;}/*** 获取目标对象列表** @return 目标对象列表*/public Class<?>[] getTargetClass() {Class<?> clazz = this.target.getClass();clazz = ClassUtils.isCglibProxyClass(clazz) ? clazz.getSuperclass() : clazz;return clazz.getInterfaces();}/*** 获取目标对象** @return 目标对象*/public Object getTarget() {return this.target;}
}
- 在
TargetSource#getTargetClass
是用于获取target
对象的接口信息的,那么这个target
可以是 JDK 代理创建,也可能是 CGLIB 创建。 - 为了保证都能正确的获取到结果,这里需要增加判断
ClassUtils.isCglibProxyClass(clazz)
。
3.4 迁移创建AOP代理方法
3.4.1 实例化感知对象处理
InstantiationAwareBeanPostProcessor.java
package com.lino.springframework.beans.factory.config;import com.lino.springframework.beans.BeansException;
import com.lino.springframework.beans.PropertyValues;/*** @description: 实例化感知对象处理*/
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {/*** 在 Bean 对象执行初始化方法之前,执行此方法** @param beanClass 对象类* @param beanName 对象名* @return 新对象* @throws BeansException 异常*/Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException;/*** 在 Bean 对象执行初始化方法之后,执行此方法** @param bean 对象* @param beanName 对象名称* @return 是否执行* @throws BeansException 异常*/boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException;/*** 在 Bean 对象实例化完成后,设置属性操作之前执行此方法** @param pvs 属性值集合* @param bean 对象* @param beanName 对象名称* @return 属性值集合* @throws BeansException 异常*/PropertyValues postProcessPropertyValues(PropertyValues pvs, Object bean, String beanName) throws BeansException;
}
3.4.2 扫描自定义注解类
AutowiredAnnotationBeanPostProcessor.java
package com.lino.springframework.beans.factory.annotation;import cn.hutool.core.bean.BeanUtil;
import com.lino.springframework.beans.BeansException;
import com.lino.springframework.beans.PropertyValues;
import com.lino.springframework.beans.factory.BeanFactory;
import com.lino.springframework.beans.factory.BeanFactoryAware;
import com.lino.springframework.beans.factory.config.ConfigurableBeanFactory;
import com.lino.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import com.lino.springframework.util.ClassUtils;
import java.lang.reflect.Field;/*** @description: 扫描自定义注解类*/
public class AutowiredAnnotationBeanPostProcessor implements InstantiationAwareBeanPostProcessor, BeanFactoryAware {...@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return null;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {return null;}@Overridepublic Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {return null;}@Overridepublic boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {return true;}
}
3.4.3 默认自动代理创建者
DefaultAdvisorAutoProxyCreator.java
package com.lino.springframework.aop.framework.autoproxy;import com.lino.springframework.aop.*;
import com.lino.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor;
import com.lino.springframework.aop.framework.ProxyFactory;
import com.lino.springframework.beans.BeansException;
import com.lino.springframework.beans.PropertyValues;
import com.lino.springframework.beans.factory.BeanFactory;
import com.lino.springframework.beans.factory.BeanFactoryAware;
import com.lino.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import com.lino.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.MethodInterceptor;
import java.util.Collection;/*** @description: 默认自动代理创建者*/
public class DefaultAdvisorAutoProxyCreator implements InstantiationAwareBeanPostProcessor, BeanFactoryAware {private DefaultListableBeanFactory beanFactory;@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {this.beanFactory = (DefaultListableBeanFactory) beanFactory;}@Overridepublic Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {return null;}@Overridepublic boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {return true;}private boolean isInfrastructureClass(Class<?> beanClass) {return Advice.class.isAssignableFrom(beanClass) || Pointcut.class.isAssignableFrom(beanClass) || Advisor.class.isAssignableFrom(beanClass);}@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (isInfrastructureClass(bean.getClass())) {return bean;}Collection<AspectJExpressionPointcutAdvisor> advisors = beanFactory.getBeansOfType(AspectJExpressionPointcutAdvisor.class).values();for (AspectJExpressionPointcutAdvisor advisor : advisors) {ClassFilter classFilter = advisor.getPointcut().getClassFilter();// 过滤匹配类if (!classFilter.matches(bean.getClass())) {continue;}AdvisedSupport advisedSupport = new AdvisedSupport();TargetSource targetSource = new TargetSource(bean);advisedSupport.setTargetSource(targetSource);advisedSupport.setMethodInterceptor((MethodInterceptor) advisor.getAdvice());advisedSupport.setMethodMatcher(advisor.getPointcut().getMethodMatcher());advisedSupport.setProxyTargetClass(false);// 返回代理对象return new ProxyFactory(advisedSupport).getProxy();}return bean;}@Overridepublic PropertyValues postProcessPropertyValues(PropertyValues pvs, Object bean, String beanName) throws BeansException {return pvs;}
}
- 关于
DefaultAdvisorAutoProxyCreator
类的操作主要就是把创建 AOP 代理的操作从postProcessBeforeInstantiation
移动到postProcessAfterInitialization
中。 - 通过设置一些 AOP 的必备参数后,返回代理对象
new ProxyFactory(advisedSupport).getProxy()
。- 这个代理对象中就包括间接调用
TargetSource#getTargetClass
的获取。
- 这个代理对象中就包括间接调用
3.5 在Bean生命周期中初始化执行
AbstractAutowireCapableBeanFactory.java
package com.lino.springframework.beans.factory.support;import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.lino.springframework.beans.BeansException;
import com.lino.springframework.beans.PropertyValue;
import com.lino.springframework.beans.PropertyValues;
import com.lino.springframework.beans.factory.*;
import com.lino.springframework.beans.factory.config.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;/*** @description: 实现默认bean创建的抽象bean工厂超类* @author: lingjian* @createDate: 2022/11/22 14:39*/
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();@Overrideprotected Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args) {Object bean = null;try {// 判断是否返回代理 Bean 对象bean = resolveBeforeInstantiation(beanName, beanDefinition);if (null != bean) {return bean;}// 实例化Beanbean = createBeanInstance(beanDefinition, beanName, args);// 实例化后判断boolean continueWithPropertyPopulation = applyBeanPostProcessorsAfterInstantiation(beanName, bean);if (!continueWithPropertyPopulation) {return bean;}// 在设置Bean属性之前,允许 BeanPostProcessor修改属性值applyBeanPostProcessorsBeforeApplyingPropertyValues(beanName, bean, beanDefinition);// 给bean填充属性applyPropertyValues(beanName, bean, beanDefinition);// 执行 Bean 的初始化方法和 BeanPostProcessor 的前置和后置处理方法bean = initializeBean(beanName, bean, beanDefinition);} catch (Exception e) {throw new BeansException("Instantiation of bean failed", e);}// 注册实现 DisposableBean 接口的 Bean 对象registerDisposableBeanIfNecessary(beanName, bean, beanDefinition);// 判断 SCOPE_SINGLETON、SCOPE_PROTOTYPEif (beanDefinition.isSingleton()) {registerSingletonBean(beanName, bean);}return bean;}/*** Bean 实例化后对于返回 false 的对象,不再执行后续设置 Bean 对象属性的操作** @param beanName 对象名称* @param bean 对象* @return 布尔值*/private boolean applyBeanPostProcessorsAfterInstantiation(String beanName, Object bean) {boolean continueWithPropertyPopulation = true;for (BeanPostProcessor beanPostProcessor : getBeanPostProcessors()) {if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor instantiationAwareBeanPostProcessor = (InstantiationAwareBeanPostProcessor) beanPostProcessor;if (!instantiationAwareBeanPostProcessor.postProcessAfterInstantiation(bean, beanName)) {continueWithPropertyPopulation = false;break;}}}return continueWithPropertyPopulation;}...private Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {for (BeanPostProcessor beanPostProcessor : getBeanPostProcessors()) {if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {Object result = ((InstantiationAwareBeanPostProcessor) beanPostProcessor).postProcessBeforeInstantiation(beanClass, beanName);if (null != result) {return result;}}}return null;}...
}
- 在
AbstractAutowireCapableBeanFactory#createBean
方法中,关注点在于initializeBean -> applyBeanPostProcessorsAfterInitialization
这块逻辑的调用,最终完成 AOP 代理对象的创建操作。
四、测试:给代理对象的属性设置值
4.1 添加测试配置
4.1.1 用户服务层实现类
UserService.java
package com.lino.springframework.test.bean;import com.lino.springframework.beans.factory.annotation.Autowired;
import com.lino.springframework.beans.factory.annotation.Value;
import com.lino.springframework.stereotype.Component;
import java.util.Random;/*** @description: 用户接口实现类*/
public class UserService implements IUserService {private String token;@Overridepublic String queryUserInfo() {try {Thread.sleep(new Random(1).nextInt(100));} catch (InterruptedException e) {e.printStackTrace();}return "张三,10001,杭州," + token;}@Overridepublic String register(String userName) {try {Thread.sleep(new Random(1).nextInt(100));} catch (InterruptedException e) {e.printStackTrace();}return "注册用户:" + userName + " success!";}@Overridepublic String toString() {return "UserService#token = {" + token + "}";}public String getToken() {return token;}public void setToken(String token) {this.token = token;}
}
4.1.2 用户前置处理
UserServiceBeforeAdvice.java
package com.lino.springframework.test.bean;import com.lino.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;/*** @description: 用户前置处理*/
public class UserServiceBeforeAdvice implements MethodBeforeAdvice {@Overridepublic void before(Method method, Object[] args, Object target) throws Throwable {System.out.println("拦截方法:" + method.getName());}
}
4.1.3 Spring属性配置文件
spring.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"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="userService" class="com.lino.springframework.test.bean.UserService"><property name="token" value="RejDlI78hu223Opo983Ds"/></bean><bean class="com.lino.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/><bean id="beforeAdvice" class="com.lino.springframework.test.bean.UserServiceBeforeAdvice"/><bean id="methodInterceptor" class="com.lino.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor"><property name="advice" ref="beforeAdvice"/></bean><bean id="pointcutAdvisor" class="com.lino.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor"><property name="expression" value="execution(* com.lino.springframework.test.bean.IUserService.*(..))"/><property name="advice" ref="methodInterceptor"/></bean></beans>
4.2 单元测试
ApiTest.java
@Test
public void test_autoProxy() {ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml");IUserService userService = applicationContext.getBean("userService", IUserService.class);System.out.println("测试结果:" + userService.queryUserInfo());
}
测试结果
拦截方法:queryUserInfo
测试结果:张三,10001,杭州,RejDlI78hu223Opo983Ds
- 测试结果看,通过对 Bean 生命周期的调整,在创建 AOP 代理对象就可以把代理对象的属性信息填充进去了。
五、总结:给代理对象的属性设置值
- 核心内容主要是完善 Bean 的生命周期,在创建类的操作中完成代理对象的创建。
- 通过这样的方式就可以让代理对象中的属性也可以随着创建过程被填充进行。
- 除核心功能的实现外,也要关注到对象的初始化操作:
CglibSubclassingInstantiationStrategy
、SimpleInstantiationStrategy
。- 这两种方式中 CGLIB 创建对象,会影响到很多地方用于接口获取的操作。因为 CGLIB 创建对象走的是 ASM 字节码生成的操作,所以和普通的 JDK 代理生成对象是不一样,需要注意。