前言
上一篇分析AbstractAutoProxyCreator
的时候留了一个悬念,本篇我们就一起来看看createProxy(...)
的全流程吧。需要指出的是createProxy(...)
整个流程还是比较复杂的,涉及到Advice
的适配和扩展、拦截器链的初始化和安装、代理的创建等等,话不多说,我们开始吧~~
梦开始的地方
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
// 在BeanDefinition中暴露原始的bean class
// 因为采用jdk dynamic proxy的话,原始的类型信息会丢失
// 进而想获取原始类型上的注解信息等就变得不可能了,因此
// spring-aop选择暴露出原始的类型信息
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
// 代理给ProxyFactory执行真的的代理创建过程
ProxyFactory proxyFactory = new ProxyFactory();
// 上篇提过,EnableAspectJAutoProxy注解有两个属性
// proxyTargetClass和exposeProxy,这里是将这两个
// 配置属性同步给了ProxyFactory,这样在执行创建的过
// 程中就能派上用场了
proxyFactory.copyFrom(this);
// proxyTargetClass不是唯一决定采用jdk dymanic proxy还是cglib subclassing的配置
// 如果BeanDefinition明确设置了originalTargetClass,那么也会采用cglib subclassing策略
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
// 否则的话表示用户希望采用jdk dynamic proxy
// 这样的话就得看看有哪些需要被代理的接口了
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 获取到Advisor数组(这一部分在上篇中有分析)
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
// 告诉工厂要增强的内容
proxyFactory.addAdvisors(advisors);
// 告诉工厂是给谁创建代理
proxyFactory.setTargetSource(targetSource);
// 扩展方法
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
// 看看在实际创建时,能不能省略对ClassFilter的调用
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// 执行代理的创建
return proxyFactory.getProxy(getProxyClassLoader());
}
如果选用JDK动态代理,那我们就得知道需要代理哪些接口,evaluateProxyInterfaces(...)
的作用就是帮我们找出所有需要被代理的接口。
protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
// 找出beanClass实现的所有接口,包括父类
Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
boolean hasReasonableProxyInterface = false;
for (Class<?> ifc : targetInterfaces) {
// InitializingBean、DisposableBean、*Aware等回调接口不再考虑范围内
// 这些接口是由spring IoC管理的,同样的还有来自JDK的Closeable、AutoCloseable,
// 也不被考虑为有效的代理接口;除此之外,还有一些众所周知的语言内部接口也不计入其中
if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) &&
ifc.getMethods().length > 0) {
// 不是上述描述的那些接口的话,可以认为是用户定义的、确实需要被代理的接口
hasReasonableProxyInterface = true;
break;
}
}
// 存在可代理接口的话,同步给ProxyFactory
if (hasReasonableProxyInterface) {
// Must allow for introductions; can't just set interfaces to the target's interfaces only.
for (Class<?> ifc : targetInterfaces) {
proxyFactory.addInterface(ifc);
}
}
else {
// 没有的话只能选择cglib subclassing了
proxyFactory.setProxyTargetClass(true);
}
}
至此AbstractAutoProxyCreator
就分析完了,现在的重点自然是ProxyFactory
,一起来看看它又是何方神圣吧。
代理的创建过程
ProxyFactory
![](https://img.haomeiwen.com/i3094543/5e4d50529259c81d.png)
ProxyFactory
的代码很少,它的出现主要是为了降低对程序猿的心智要求——简化了其父类ProxyCreatorSupport
的使用,因此我们就直接看ProxyCreatorSupport
吧。
ProxyCreatorSupport
可以看到ProxyCreatorSupport
继承自AdvisedSupport
,而AdvisedSupport
又实现了Advised
接口。在第一篇中我们就介绍过Advised
接口,它被设计来保存AOP配置信息,比如目标对象是谁?是使用JDK动态代理还是CGLIB
?如果使用JDK动态代理,需要被代理的接口有哪些?围绕目标对象的Advisor
有哪些?AdvisedSupport
的实现也是很简单的,就不耽误篇幅去分析了。
作为一款设计模式泛滥的框架(bushi),spring-aop
怎么能让ProxyCreatorSupport
一个人偷偷把活干了呢,那必须俄罗斯套娃,继续代理给AopProxyFactory
。从设计上看,ProxyCreatorSupport
是一个上下文对象,它维护着AOP配置信息,并将这些配置信息交给它管理的AopProxyFactory
去执行最后的创建逻辑,也可以说是职责单一化吧。
AopProxyFactory
只有一个默认实现——DefaultAopProxyFactory
,核心方法如下:
@Override
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.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
可以看到,就是一个选择JDK动态代理还是CGLib动态生成子类的过程。挑一个,我们来分析JdkDynamicAopProxy
吧。
JdkDynamicAopProxy
![](https://img.haomeiwen.com/i3094543/884e6e50dc73cbf1.png)
生成JDK动态代理必然要实现InvocationHandler
接口,而AopProxy
作为一个工厂接口,提供了获取代理入口。
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
// 除了evaluateProxyInterfaces(...)算法获取的接口外
// Spring AOP还会添加Advised、SpringProxy和DecoratingProxy这几个代理接口
// Advised用于向外暴露aop配置信息
// SpringProxy作为标记接口,可用来检测某个对象是否是动态代理
// DecoratingProxy可用于获取代理的真实类型
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
// 看一下被代理接口是否有定义equals和hashCode方法
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
// 创建动态代理
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
接下来看看InvocationHandler
是如何实现的吧。
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
// 根据exposeProxy的配置情况
// 决定是否要向外暴露代理对象
boolean setProxyContext = false;
// 获取TargetSource
// 对目标对象target的获取则会延迟到最后一步
TargetSource targetSource = this.advised.targetSource;
// 目标对象,也即被代理对象
Object target = null;
try {
// 未自定义equals,转而判断代理是否equal
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
return equals(args[0]);
}
// 未自定义hashCode,返回代理的hashCode
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
return hashCode();
}
// DecoratingProxy只定义了一个方法#getDecoratedClass()
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// 获取目标对象的类型
return AopProxyUtils.ultimateTargetClass(this.advised);
}
// Advised接口中定义的方法
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
// 返回值
Object retVal;
// 需要暴露代理对象的话
if (this.advised.exposeProxy) {
// 通过AopContext暴露出去
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// 接下来要执行的就是目标对象上的方法啦
// 首先要获取目标对象
target = targetSource.getTarget();
// 目标对象的类型
Class<?> targetClass = (target != null ? target.getClass() : null);
// 获取作用在方法上的拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// 没有任何Advice的话,直接调用原方法
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// 有Advice,就需要在此连接点上安装拦截器链了
// 对应成代码,就是创建一个ReflectiveMethodInvocation对象
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// 通过拦截器链执行方法
// 拦截器链内部会自动转向链中的下一个拦截器
retVal = invocation.proceed();
}
Class<?> returnType = method.getReturnType();
// 如果方法返回this,替换成代理对象
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
retVal = proxy;
}
// 原始类型和void不能有null值,fail fast
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
// 恢复AopContext的原内容
if (setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
}
}
}
InvocationHandler
的实现中有两个需要注意的地方:
- 获取作用在连接点上的拦截器链——
this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass)
- 安装拦截器链到连接点上——
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain)
拦截器链
获取作用在连接点上的拦截器链
拦截器链的获取并不是由AdvisedSupport
直接完成的,它也只是个中间商,实际是由AdvisorChainFactory
代为完成的。
@Override
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method,
@Nullable Class<?> targetClass) {
// AdvisorAdapterRegistry负责Advice的适配和扩展
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
// 获取当前已有的所有Advisor
Advisor[] advisors = config.getAdvisors();
// 保存所有可用的拦截器
List<Object> interceptorList = new ArrayList<>(advisors.length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
Boolean hasIntroductions = null;
for (Advisor advisor : advisors) {
// Advisor几乎都是PointcutAdvisor类型
// 这里已经cover了90%的可能性
if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
// 1. 进行类的匹配
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
boolean match;
// 跳过Introduction,用得太少,不说了
if (mm instanceof IntroductionAwareMethodMatcher) {
if (hasIntroductions == null) {
hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
}
match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
}
else {
// 2. 进行方法匹配
match = mm.matches(method, actualClass);
}
if (match) {
// 获取隐藏在Advisor下的拦截器
// Spring AOP是基于MethodInterceptor的
// BeforeAdvice/AfterAdvice最终都要转换成MethodInterceptor
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
// 如果还需要运行时判断
if (mm.isRuntime()) {
// 此时是无法进行runtime match的
// 只有在方法真正调用时才能进行
// 当前能做的是把这些信息记录下来,这就是InterceptorAndDynamicMethodMatcher做的事
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
// 不需要runtime match的话,此时就可以确定下来了
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
// 忽略Introduction吧
else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
else {
// 既不是PointcutAdvisor也不是IntroductionAdvisor
// 直接加入吧,可以理解成PointcutAdvisor.getPointcut() == Pointcut.TRUE
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
Advice的适配和扩展
AdvisorAdapter
是一个适配器接口,用来将Advice
包装成MethodInterceptor
,AdvisorAdapterRegistry
则提供了对AdvisorAdapter
的管理功能。以MethodBeforeAdvice
为例,一起来看看AdvisorAdapter
是如何进行适配的吧。
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {
@Override
public boolean supportsAdvice(Advice advice) {
// 此适配器只对MethodBeforeAdvice有用
return (advice instanceof MethodBeforeAdvice);
}
@Override
public MethodInterceptor getInterceptor(Advisor advisor) {
MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
// 将MethodBeforeAdvice包装成MethodBeforeAdviceInterceptor
return new MethodBeforeAdviceInterceptor(advice);
}
}
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
// 持有MethodBeforeAdvice作为代理
private final MethodBeforeAdvice advice;
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
// 在方法执行前使用增强
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
// 转向链中的下一个拦截器
return mi.proceed();
}
}
Advice
的适配是不是还挺简单的?再看看AdvisorAdapterRegistry
呗。
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
private final List<AdvisorAdapter> adapters = new ArrayList<>(3);
public DefaultAdvisorAdapterRegistry() {
// 注册内置的几个适配器,包括方法执行前、返回后和抛出异常时的拦截器
registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
registerAdvisorAdapter(new AfterReturningAdviceAdapter());
registerAdvisorAdapter(new ThrowsAdviceAdapter());
}
/**
* 将Advice包装成Advisor
*/
@Override
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
// 本身是Advisor,直接返回
if (adviceObject instanceof Advisor) {
return (Advisor) adviceObject;
}
// 不是Advisor还不是Advice
if (!(adviceObject instanceof Advice)) {
throw new UnknownAdviceTypeException(adviceObject);
}
// MethodInterceptor就不用适配了
Advice advice = (Advice) adviceObject;
if (advice instanceof MethodInterceptor) {
return new DefaultPointcutAdvisor(advice);
}
// 否则的话得看看框架支不支持
for (AdvisorAdapter adapter : this.adapters) {
if (adapter.supportsAdvice(advice)) {
return new DefaultPointcutAdvisor(advice);
}
}
throw new UnknownAdviceTypeException(advice);
}
/**
* 获取Advisor持有的MethodInterceptor
*/
@Override
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList<>(3);
Advice advice = advisor.getAdvice();
// Advice本身就是MethodInterceptor
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
// Advice的实现类本身是可以实现多个Advice接口的
// 比如一个类可以同时实现MethodBeforeAdvice/AfterReturningAdvice/MethodInterceptor
// 因而这里不是if-else,而是if-if
for (AdvisorAdapter adapter : this.adapters) {
// 看看是不是某个支持的Advice
if (adapter.supportsAdvice(advice)) {
// 转换成MethodInterceptor
interceptors.add(adapter.getInterceptor(advisor));
}
}
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
return interceptors.toArray(new MethodInterceptor[0]);
}
/**
* 注册适配器,除了spring内置的,我们也可以添加自定义的适配器
*/
@Override
public void registerAdvisorAdapter(AdvisorAdapter adapter) {
this.adapters.add(adapter);
}
}
安装拦截器链到连接点
这部分的核心是ProxyMethodInvocation
,它通过构造函数完成了拦截器链的安装。
protected ReflectiveMethodInvocation(
Object proxy, @Nullable Object target, Method method, @Nullable Object[] arguments,
@Nullable Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers) {
// 代理对象
this.proxy = proxy;
// 被代理对象
this.target = target;
// 被代理对象的类型
this.targetClass = targetClass;
// 连接点对应的方法
this.method = BridgeMethodResolver.findBridgedMethod(method);
// 方法参数
this.arguments = AopProxyUtils.adaptArgumentsIfNecessary(method, arguments);
// 拦截器链
this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers;
}
那么拦截器链如何工作呢?
public Object proceed() throws Throwable {
// currentInterceptorIndex起始值-1
// 如果拦截器链中没有任何拦截器,直接调用目标方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
// 否则获取拦截器链中的一个拦截器
// currentInterceptorIndex递增,保证下次获取的是下一个拦截器
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
// 前面说过InterceptorAndDynamicMethodMatcher是一个holder
// 它持有的MethodMatcher是需要runtime match的
// 而当前正是方法调用的时候
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
// 进行runtime match
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
// 匹配上的话调用拦截器,而拦截器内部又会调用 mi.proceed()
// 这样的话就可以转到链上的下一个拦截器了,是不是很精妙?
return dm.interceptor.invoke(this);
}
else {
// 没匹配上,跳过这个拦截器转向下一个
return proceed();
}
}
else {
// 普通的MethodInterceptor,调用它,并转向链中的下一个拦截器
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
@Nullable
protected Object invokeJoinpoint() throws Throwable {
return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
}
后记
至此,spring-aop
整个流程就分析完了,至于掌握了原理后怎么玩出花儿来,就靠想象了。
网友评论