前言
在AnnotationAwareAspectJAutoProxyCreator的父类AbstractAutoProxyCreator的postProcessBeforeInstantiation
方法中,有一个TargetSource的设计:
代码清单1:AbstractAutoProxyCreator.java
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
// ......
// 源码注释:如果我们有一个自定义的TargetSource,在这里创建代理;TargetSource将以自定义方式处理目标实例。
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return null;
}
由 代码清单1 可知,TargetSource的设计与AOP代理有关。
9.4 TargetSource的设计
实际上,AOP的代理并不是代理目标对象本身,而是目标对象经过包装后的TargetSource对象。
9.4.1 与Java原生动态代理的区别
在Java原生动态代理中,代理对象中直接组合了原始对象:
而在AOP中,代理对象并没有直接代理target,而是给target加了一个“壳”,即TargetSource:
TargetSource对象可以看作目标对象的一个包装、容器,Java原生动态代理在执行method.invoke(target, args)
时,获取的是目标对象;但被TargetSource包装后,就只能改用method.invoke(targetSource.getTarget(), args)
进行。
9.4.2 TargetSource的好处
上述两种方式,最终结果都会拿到目标对象target,但getTarget
方法可以提供一个可扩展的切入点,决定如何返回目标对象。
例如,每次getTarget
方法返回的target对象可以不一致,或者从一个对象池中获取。
总的来说,让AOP代理TargetSource的好处是可以控制每次方法调用的作用的具体对象实例,从而让方法的调用更灵活。
9.4.3 TargetSource的结构
代码清单2:TargetSource.java
public interface TargetSource extends TargetClassAware {
Class<?> getTargetClass();
boolean isStatic();
Object getTarget() throws Exception;
void releaseTarget(Object target) throws Exception;
}
由 代码清单2 可知,TargetSource是一个接口,定义了几个方法:
- getTarget:获取target对象。
- releaseTarget:释放target对象。
- isStatic:是否静态bean对象。单实例bean对象就为“静态bean对象”,原型bean对象就为“非静态bean对象”。
9.4.4 SpringFramework中提供的TargetSource
SpringFramework针对不同场景和不同需求,预设了几个TargetSource的实现:
- SingletonTargetSource:单实例TargetSource,每次调用
getTarget
方法都会返回同一个目标对象(与Java原生动态代理无任何区别); - PrototypeTargetSource:原型TargetSource,每次调用
getTarget
方法都会从BeanFactory中创建一个全新的目标对象(被它包装的目标对象必须为原型bean对象); - CommonsPool2TargetSource:内部维护了一个对象池,每次调用
getTarget
方法都会从对象池中提取出对象(底层使用Apache的ObjectPool); - ThreadLocalTargetSource:本地线程TargetSource,每次调用
getTarget
方法都会从它所处的线程中提取目标对象(由于每个线程都有一个TargetSource,因此被它包装的目标对象也必须为原型bean对象); - HotSwappableTargetSource:支持热替换的TargetSource,内部维护一个可以热替换的目标对象引用,每次调用
getTarget
方法都会返回它。
9.5 代理对象生成的核心:wrapIfNecessary
在 SpringBoot源码解读与原理分析(二十八)AOP模块的生命周期(一) 9.2.3.2 postProcessAfterInitialization 中提到,bean对象的初始化会被BeanPostProcessor的postProcessAfterInitialization
方法处理,进入AnnotationAwareAspectJAutoProxyCreator的postProcessAfterInitialization
方法中,该方法又要调用wrapIfNecessary
方法尝试创建代理对象。
代码清单3:AbstractAutoProxyCreator.java
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 判断是否是不会被增强的对象
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// 如果上面的判断都不成立,则决定是否进行代理对象的创建
// 先获取增强器
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 创建代理对象的动作
// 创建SingletonTargetSource,将bean对象包装起来
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
由 代码清单3 可知,wrapIfNecessary
方法的逻辑很清晰,先判断是否是不会被增强的对象,如果不是则会获取增强器集合,并创建由SingletonTargetSource包装的代理对象。
9.5.1 getAdvicesAndAdvisorsForBean
从方法名就能知道,getAdvicesAndAdvisorsForBean
方法会根据当前正在初始化的bean对象,匹配可织入通知的增强器。
代码清单4:AbstractAdvisorAutoProxyCreator.java
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 获取所有增强器
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 筛选出可以切入当前bean对象的增强器
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
// 添加额外的增强器
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
// 增强器排序
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
由 代码清单4 可知,getAdvicesAndAdvisorsForBean
方法又会调用findEligibleAdvisors
方法,后者的逻辑也很清晰:获取所有增强器;筛选出可以切入当前bean对象的增强器;添加额外的增强器;增强器排序。
9.5.1.1 findCandidateAdvisors
这个方法已经梳理过,详见 SpringBoot源码解读与原理分析(二十八)AOP模块的生命周期(一) 9.3 Advisor与切面类的收集 ,是同一个方法。
9.5.1.2 findAdvisorsThatCanApply
获取到所有候选增强器之后,接着匹配可以切入当前正在初始化的bean对象的增强器。
代码清单5:AbstractAdvisorAutoProxyCreator.java
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
} finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
代码清单6:AopUtils.java
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new ArrayList<>();
// 匹配引介增强器
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
// 匹配普通方法增强器
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
由 代码清单5、6 可知,匹配动作最终由AopUtils的findAdvisorsThatCanApply
实现,主体逻辑分为匹配引介增强器、匹配普通方法增强器。在实际项目开发中,几乎不会用到引介通知,因此重点放在普通方法通知封装的增强器。
代码清单7:AopUtils.java
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
if (advisor instanceof IntroductionAdvisor) {
// 对于引介增强器,直接强转,使用类级过滤器匹配
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
else if (advisor instanceof PointcutAdvisor) {
// 普通方法切入的增强器匹配逻辑
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// 位置类型,默认可以匹配
return true;
}
}
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
// 如果切入点无法应用于当前bean对象,则直接返回false
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
// ......
// 收集当前bean对象继承的父类和实现的接口
// 因为切入点表达式可能切的是父类或接口
Set<Class<?>> classes = new LinkedHashSet<>();
if (!Proxy.isProxyClass(targetClass)) {
classes.add(ClassUtils.getUserClass(targetClass));
}
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
for (Class<?> clazz : classes) {
// 逐个判断每个方法能否被当前切入点表达式切入,能则立即返回true
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
if (introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
由 代码清单7 可知,canApply
方法会针对不同类型的增强器分别采用不同的判断逻辑。对于普通方法通知封装的增强器,会转调重载的canApply
方法。在该重载方法中,利用MethodMatcher逐个判断每个方法能否被当前切入点表达式切入。
9.5.1.3 extendAdvisors
由 代码清单4 可知,getAdvicesAndAdvisorsForBean
方法的第三步是添加额外的增强器extendAdvisors
方法。
代码清单8:AspectJAwareAdvisorAutoProxyCreator.java
protected void extendAdvisors(List<Advisor> candidateAdvisors) {
AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors);
}
代码清单9:AspectJProxyUtils.java
public static boolean makeAdvisorChainAspectJCapableIfNecessary(List<Advisor> advisors) {
// Don't add advisors to an empty list; may indicate that proxying is just not required
if (!advisors.isEmpty()) {
// 判断是否有AspectJ封装的增强器
boolean foundAspectJAdvice = false;
for (Advisor advisor : advisors) {
if (isAspectJAdvice(advisor)) {
foundAspectJAdvice = true;
break;
}
}
// 如果发现有AspectJ封装的增强器,则添加一个ExposeInvocationInterceptor.ADVISOR
if (foundAspectJAdvice && !advisors.contains(ExposeInvocationInterceptor.ADVISOR)) {
advisors.add(0, ExposeInvocationInterceptor.ADVISOR);
return true;
}
}
return false;
}
由 代码清单8、9 可知,extendAdvisors
会判断当前可用的增强器中是否有AspectJ封装的增强器,如果有则在整个增强器列表的最前端添加一个ExposeInvocationInterceptor.ADVISOR。
代码清单10:ExposeInvocationInterceptor.java
public static final ExposeInvocationInterceptor INSTANCE = new ExposeInvocationInterceptor();
public static final Advisor ADVISOR = new DefaultPointcutAdvisor(INSTANCE) {
@Override
public String toString() {
return ExposeInvocationInterceptor.class.getName() +".ADVISOR";
}
};
private static final ThreadLocal<MethodInvocation> invocation =
new NamedThreadLocal<>("Current AOP method invocation");
public Object invoke(MethodInvocation mi) throws Throwable {
MethodInvocation oldInvocation = invocation.get();
invocation.set(mi);
try {
return mi.proceed();
} finally {
invocation.set(oldInvocation);
}
}
由 代码清单10 可知,ExposeInvocationInterceptor.ADVISOR是一个DefaultPointcutAdvisor,是一个对所有bean对象都生效的增强器。其invoke
方法会向当前线程的ThreadLocal中放入当前正在执行的代理对象的方法执行包装(MethodInvocation)。
并且,把该增强器放在增强器列表的最前端,那后面的增强器都可以获取到当前正在执行的MethodInvocation对象。
9.5.2 createProxy
回到wrapIfNecessary
方法,getAdvicesAndAdvisorsForBean
方法执行完毕后,下一步就是创建代理对象createProxy
方法。
代码清单11:AbstractAutoProxyCreator.java
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
// ......
// 代理工厂的初始化
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
// 根据AOP的设计,决定是否强制使用Cglib
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
// Cglib动态代理直接记录被代理bean对象的所属类即可
proxyFactory.setProxyTargetClass(true);
} else {
// 解析被代理bean对象所属类的所有实现的接口
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 收集整理要织入目标对象的通知增强器
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// 创建代理对象
return proxyFactory.getProxy(getProxyClassLoader());
}
由 代码清单11 可知,createProxy
方法的核心步骤是:收集整理要织入目标对象的通知增强器;创建代理对象。
9.5.2.1 buildAdvisors
代码清单12:AbstractAutoProxyCreator.java
protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
// 适配SpringFramework原生AOP的MethodInterceptor
Advisor[] commonInterceptors = resolveInterceptorNames();
List<Object> allInterceptors = new ArrayList<>();
if (specificInterceptors != null) {
if (specificInterceptors.length > 0) {
allInterceptors.addAll(Arrays.asList(specificInterceptors));
}
if (commonInterceptors.length > 0) {
if (this.applyCommonInterceptorsFirst) {
allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
} else {
allInterceptors.addAll(Arrays.asList(commonInterceptors));
}
}
}
// logger ...
// 将 支持转换/包装为Advisor类型的对象 适配成Advisor
Advisor[] advisors = new Advisor[allInterceptors.size()];
for (int i = 0; i < allInterceptors.size(); i++) {
advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
}
return advisors;
}
由 代码清单12 可知,buildAdvisors
方法将收集好的增强器specificInterceptors放入了allInterceptors,并将其中的支持转换/包装为Advisor类型的对象(即MethodInterceptor和AdvisorAdapter)适配成Advisor。
9.5.2.2 proxyFactory.getProxy
代码清单13:ProxyFactory.java
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
由 代码清单13 可知,getProxy
方法又分为两步:
(1)createAopProxy
代码清单14:ProxyCreatorSupport.java
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
public AopProxyFactory getAopProxyFactory() {
return this.aopProxyFactory;
}
由 代码清单14 可知,createAopProxy
方法会先获取一个AopProxyFactory,在调用其createAopProxy
方法得到一个AopProxy。
默认的AopProxyFactory类型是DefaultAopProxyFactory类。
代码清单15:DefaultAopProxyFactory.java
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
// 如果要代理的本身是接口,或者已经被JDK动态代理的代理对象,则使用JDK动态代理
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
// 否则使用Cglib动态代理
return new ObjenesisCglibAopProxy(config);
} else {
return new JdkDynamicAopProxy(config);
}
}
(2)getProxy
创建完AopProxy,接下来开始创建代理对象。
- JDK动态代理JdkDynamicAopProxy
代码清单16:JdkDynamicAopProxy.java
public Object getProxy(@Nullable ClassLoader classLoader) {
// logger ...
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
由 代码清单16 可知,底层创建代理对象使用的是Proxy.newProxyInstance
。
- Cglib动态代理ObjenesisCglibAopProxy
代码清单17:ObjenesisCglibAopProxy.java
public Object getProxy(@Nullable ClassLoader classLoader) {
// ......
// Configure CGLIB Enhancer...
Enhancer enhancer = createEnhancer();
// 设置类加载器、父类、接口等信息
// ......
// 创建代理对象
return createProxyClassAndInstance(enhancer, callbacks);
}
由 代码清单17 可知,Cglib动态代理的创建逻辑,核心动作还是对Enhancer进行操作。
至此,代理对象被成功创建,整个AOP通知织入的流程结束。随着IOC容器刷新完成,所有代理对象也都全部创建完毕。
······
本节完,更多内容请查阅分类专栏:SpringBoot源码解读与原理分析