【Spring】AOP实现原理(三):创建代理
AbstractAutoProxyCreator
在AbstractAutoProxyCreator的wrapIfNecessary方法中,调用getAdvicesAndAdvisorsForBean方法获取到所有的Advisor之后,就可以创建代理对象了,创建的具体过程在createProxy方法中:
- 创建代理工厂ProxyFactory
- 调用buildAdvisors构建Advisor,入参是getAdvicesAndAdvisorsForBean获取到的Advice和Advisor,里面又调用了AdvisorAdapterRegistry的wrap方法判断Advice是否是Advisor类型,这一步主要是对通知Advice进行校验,如果通知不是Advisor类型将其包装为Advisor
- 通过代理工厂ProxyFactory生成代理对象
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
/**
* 是否有必要生成代理对象
* @param bean
* @param beanName
* @param cacheKey
* @return
*/
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;
}
// 获取Advices和Advisors
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 创建代理,specificInterceptors就是获取到的Advices和Advisors
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;
}
/**
* 创建代理对象
*/
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
// 1.创建代理工厂
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 2.构建Advisor
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
// 设置Advisor
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// 3.生成代理对象
return proxyFactory.getProxy(getProxyClassLoader());
}
}
构建Advisor
AbstractAutoProxyCreator的buildAdvisors主要是对通知Advice进行校验,如果通知不是Advisor类型将其包装为Advisor,具体是通过AdvisorAdapterRegistry的wrap方法实现的:
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
// 调用GlobalAdvisorAdapterRegistry的getInstance获取AdvisorAdapterRegistry实例
private AdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.getInstance();
/**
* 构建Advisors,specificInterceptors是上一步获取到的Advice和Advisor
*/
protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
// Handle prototypes correctly...
Advisor[] commonInterceptors = resolveInterceptorNames();
List<Object> allInterceptors = new ArrayList<>();
if (specificInterceptors != null) {
// 将获取到的Advice和Advisor添加到拦截器中
allInterceptors.addAll(Arrays.asList(specificInterceptors));
if (commonInterceptors.length > 0) {
if (this.applyCommonInterceptorsFirst) {
allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
}
else {
allInterceptors.addAll(Arrays.asList(commonInterceptors));
}
}
}
if (logger.isTraceEnabled()) {
int nrOfCommonInterceptors = commonInterceptors.length;
int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);
logger.trace("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
" common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
}
// 创建Advisor集合
Advisor[] advisors = new Advisor[allInterceptors.size()];
for (int i = 0; i < allInterceptors.size(); i++) {
// 调用AdvisorAdapterRegistry的wrap方法将通知包装为Advisor进行增强,在DefaultAdvisorAdapterRegistry中实现
advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
}
return advisors;
}
}
AdvisorAdapterRegistry
在GlobalAdvisorAdapterRegistry中可以看到使用的是DefaultAdvisorAdapterRegistry:
public final class GlobalAdvisorAdapterRegistry {
/**
* 使用DefaultAdvisorAdapterRegistry
*/
private static AdvisorAdapterRegistry instance = new DefaultAdvisorAdapterRegistry();
/**
* 返回AdvisorAdapterRegistry
*/
public static AdvisorAdapterRegistry getInstance() {
return instance;
}
}
DefaultAdvisorAdapterRegistry
DefaultAdvisorAdapterRegistry中的wrap方法主要逻辑如下:
- 如果当前的通知已经是Advisor类型直接返回即可
- 如果当前的通知不是Advice类型,抛出异常
- 将通知转为Advice,对通知进行判断
- 如果通知是MethodInterceptor方法拦截器,将其包装为DefaultPointcutAdvisor
- 如果不是MethodInterceptor,遍历Adapter适配器,找出支持当前通知的适配器,再将通知包装为DefaultPointcutAdvisor返回
- 非以上几种情况抛出异常
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
@Override
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
// 如果已经是Advisor,返回即可
if (adviceObject instanceof Advisor) {
return (Advisor) adviceObject;
}
// 如果不是Advice类型,抛出异常
if (!(adviceObject instanceof Advice)) {
throw new UnknownAdviceTypeException(adviceObject);
}
// 转为Advice
Advice advice = (Advice) adviceObject;
// 如果是一个方法拦截器
if (advice instanceof MethodInterceptor) {
// 包装为DefaultPointcutAdvisor
return new DefaultPointcutAdvisor(advice);
}
for (AdvisorAdapter adapter : this.adapters) {
// 判断Advisor适配器是否支持当前的Advice
if (adapter.supportsAdvice(advice)) {
// 包装为DefaultPointcutAdvisor
return new DefaultPointcutAdvisor(advice);
}
}
// 抛出异常
throw new UnknownAdviceTypeException(advice);
}
}
生成代理对象
上一步中已经对所有的Advice进行了校验,转为了Advisor进行增强,接下来就可以生成代理对象了,具体实现在ProxyFactory的getProxy中:
- 调用createAopProxy获取AopProxy,AopProxy是一个接口,定义了getProxy获取代理对象的方法,它有两个实现类分别为CglibAopProxy和JdkDynamicAopProxy
- 调用AopProxy的getProxy方法获取代理对象
public class ProxyFactory extends ProxyCreatorSupport {
/**
* 获取代理对象
*/
public Object getProxy(@Nullable ClassLoader classLoader) {
// 通过工厂创建AOP代理对象,createAopProxy方法在ProxyCreatorSupport中实现
return createAopProxy().getProxy(classLoader);
}
}
createAopProxy创建AopProxy
createAopProxy的实现逻辑在ProxyFactory的父类ProxyCreatorSupport中实现,它使用了工厂模式生成代理对象:
- 调用getAopProxyFactory方法获取AopProxyFactory,在无参构造函数中可以看的默认使用的工厂是DefaultAopProxyFactory
- 调用AopProxyFactory的createAopProxy方法创建代理对象
// ProxyCreatorSupport
public class ProxyCreatorSupport extends AdvisedSupport {
// AOP代理工厂
private AopProxyFactory aopProxyFactory;
/**
* 无参构造函数
*/
public ProxyCreatorSupport() {
// 工厂的实现默认使用DefaultAopProxyFactory
this.aopProxyFactory = new DefaultAopProxyFactory();
}
/**
* 带有AopProxyFactory参数的构造函数
*/
public ProxyCreatorSupport(AopProxyFactory aopProxyFactory) {
Assert.notNull(aopProxyFactory, "AopProxyFactory must not be null");
this.aopProxyFactory = aopProxyFactory;
}
/**
* 创建AopProxy
*/
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
// 1.调用getAopProxyFactory获取AopProxy,2.调用AopProxy的createAopProxy创建代理对象
return getAopProxyFactory().createAopProxy(this);
}
/**
* 返回AOP代理工厂
*/
public AopProxyFactory getAopProxyFactory() {
return this.aopProxyFactory;
}
}
DefaultAopProxyFactory
DefaultAopProxyFactory中创建AOP代理的逻辑如下:
- 获取目标对象的Class信息
- 对Class进行判断:
- 如果是一个接口或者isProxyClass返回true使用JDK动态代理生成代理对象,isProxyClass方法在JDK的Proxy中实现,返回true的条件为目标类是java.lang.reflect.Proxy的子类并且缓存中包含目标类
- 如果上一个条件不满足则使用CGLIB生成代理对象
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
// 获取目标对象的Class信息
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);
}
// 否则使用CGLIB生成代理对象
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
}
// java.lang.reflect.Proxy
public class Proxy implements java.io.Serializable {
public static boolean isProxyClass(Class<?> cl) {
// 是否是java.lang.reflect.Proxy的子类并且缓存中包含目标类
return Proxy.class.isAssignableFrom(cl) && proxyClassCache.containsValue(cl);
}
}
到此AopProxy已经创建成功,接下来以JdkDynamicAopProxy为例查看getProxy获取代理对象过程。
getProxy获取代理对象
JdkDynamicAopProxy是通过JDK的动态代理实现代理创建的,可以看到它实现了InvocationHandler接口,关于JDK的动态代理实现原理可参考【JAVA】动态代理,这里我们需要关注getProxy和invoke方法:
- getProxy:创建代理对象
- invoke:当代理对象中引用的方法执行时会进入这个方法中
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
@Override
public Object getProxy() {
return getProxy(ClassUtils.getDefaultClassLoader());
}
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
// 生成代理对象
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 先省略
}
}
getProxy创建代理对象
可以看到是通过JDK中Proxy的newProxyInstance生成代理对象的:
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
// 生成代理对象
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
}
invoke方法
当调用AOP中需要被通知拦截的方法时,会进入到invoke方法,比较核心的是getInterceptorsAndDynamicInterceptionAdvice获取拦截器链,如果为空直接通过反射执行目标方法即可,如果不为空,将方法包装为MethodInvocation,然后执行拦截器链:
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
/** AdvisedSupport */
private final AdvisedSupport advised;
/**
* InvocationHandler中定义的invoke方法,当目标方法执行时会进入到这个方法中
* @param proxy 代理对象
* @param method 需要被执行的目标方法
* @param args
* @return
* @throws Throwable
*/
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
// 如果是equals方法
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// 如果是hashCode方法
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// 如果方法所在类是DecoratingProxy类
return AopProxyUtils.ultimateTargetClass(this.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) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// 获取当前方法的拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// 校验拦截器链是否为空
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
// 如果为空直接执行目标方法即可
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// 创建MethodInvocation
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// 执行拦截器链
retVal = invocation.proceed();
}
// 获取方法返回值
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
retVal = proxy;
}
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()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
}
获取方法的拦截器链
获取目标方法的拦截器链在AdvisedSupport中实现,它主要用于将适用于当前方法的Advisor转为方法拦截器,首先它先从缓存中查询,如果未查询到,调用advisorChainFactory方法的getInterceptorsAndDynamicInterceptionAdvice进行获取,在DefaultAdvisorChainFactory中实现:
public class AdvisedSupport extends ProxyConfig implements Advised {
/** AdvisorChainFactory,默认使用DefaultAdvisorChainFactory*/
AdvisorChainFactory advisorChainFactory = new DefaultAdvisorChainFactory();
/**
* 获取方法的拦截器链
*/
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
// 构建缓存KEY
MethodCacheKey cacheKey = new MethodCacheKey(method);
// 从缓存获取
List<Object> cached = this.methodCache.get(cacheKey);
if (cached == null) {
// 如果未从缓存中获取到,调用getInterceptorsAndDynamicInterceptionAdvice获取方法的拦截器链
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this, method, targetClass);
// 加入到缓存
this.methodCache.put(cacheKey, cached);
}
return cached;
}
}
DefaultAdvisorChainFactory
getInterceptorsAndDynamicInterceptionAdvice中先获取了所有的Advisor,然后遍历Advisor,对Advisor进行判断:
如果是PointcutAdvisor类型,将Advisor转为PointcutAdvisor,然后获取Pointcut切点的ClassFilter,通过matches方法判断当前方法所属的class是否匹配,如果匹配,则从切点中获取MethodMatcher方法匹配器,调用它的matches方法判断切点与当前方法是否匹配,如果也匹配,调用AdvisorAdapterRegistry的getInterceptors将Advisor转为方法拦截器
如果是引入通知IntroductionAdvisor,并且ClassFilter的matches与当前类匹配,调用AdvisorAdapterRegistry的getInterceptors将Advisor转为方法拦截器
非以上两种情况,调用AdvisorAdapterRegistry的getInterceptors将Advisor转为方法拦截器
可以看到以上三种情况,最后都是调用了AdvisorAdapterRegistry获取拦截器的,接下来就进入AdvisorAdapterRegistry中查看getInterceptors的具体实现。
public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializable {
/**
* 获取方法的拦截器链
*/
@Override
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {
// 获取AdvisorAdapterRegistry
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;
// 遍历Advisor
for (Advisor advisor : advisors) {
// 如果是PointcutAdvisor类型
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
// 调用matches方法判断与当前class是否匹配
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
// 获取方法匹配器MethodMatcher
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
boolean match;
// 如果是IntroductionAwareMethodMatcher
if (mm instanceof IntroductionAwareMethodMatcher) {
if (hasIntroductions == null) {
hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
}
match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
}
else {
// 调用MethodMatcher的matches方法匹配
match = mm.matches(method, actualClass);
}
if (match) {
// 如果匹配,从registry中获取方法拦截器
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
if (mm.isRuntime()) {
// Creating a new object instance in the getInterceptors() method
// isn't a problem as we normally cache created chains.
for (MethodInterceptor interceptor : interceptors) {
// 将拦截器封装为InterceptorAndDynamicMethodMatcher
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
else if (advisor instanceof IntroductionAdvisor) {
// 如果是引入通知IntroductionAdvisor
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
}
DefaultAdvisorAdapterRegistry
在DefaultAdvisorAdapterRegistry的构造函数中注册了三种AdvisorAdapter,使用了适配器模式将Advisor转换为方法拦截器MethodInterceptor,三种AdvisorAdapter分别为:
- MethodBeforeAdviceAdapter:支持前置通知MethodBeforeAdvice
- AfterReturningAdviceAdapter:支持返回通知AfterReturningAdvice
- ThrowsAdviceAdapter:支持ThrowsAdvice
AspectJAfterThrowingAdvice、AspectJAroundAdvice和AspectJAfterAdvice本身已经实现了MethodInterceptor接口,所以不需要进行转换:
在getInterceptors方法中,对Advisor进行判断,如果本身已经是MethodInterceptor直接返回即可,否则遍历所有的AdvisorAdapter,找出支持当前Advisor的Adapter,然后将Advisor转为MethodInterceptor:
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
private final List<AdvisorAdapter> adapters = new ArrayList<>(3);
/**
* 注册AdvisorAdapter
*/
public DefaultAdvisorAdapterRegistry() {
// 注册MethodBeforeAdviceAdapter
registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
// 注册AfterReturningAdviceAdapter
registerAdvisorAdapter(new AfterReturningAdviceAdapter());
// 注册ThrowsAdviceAdapter
registerAdvisorAdapter(new ThrowsAdviceAdapter());
}
@Override
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList<>(3);
// 从Advisor中获取Advice
Advice advice = advisor.getAdvice();
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
// 遍历Adapter
for (AdvisorAdapter adapter : this.adapters) {
// 判断是否支持当前的通知
if (adapter.supportsAdvice(advice)) {
// 通过Adapter获取拦截器
interceptors.add(adapter.getInterceptor(advisor));
}
}
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
return interceptors.toArray(new MethodInterceptor[0]);
}
}
AdvisorAdapter有三个实现类,以MethodBeforeAdviceAdapter为例查看一下supportsAdvice和getInterceptor的实现:
在supportsAdvice方法中可以看到它支持的是MethodBeforeAdvice方法前置通知
在getInterceptor方法中,首先从Advisor中获取到了通知,然后将通知封装为MethodBeforeAdviceInterceptor返回
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();
// 封装为MethodBeforeAdviceInterceptor
return new MethodBeforeAdviceInterceptor(advice);
}
}
执行目标方法
回顾invoke方法中的主要逻辑,在获取到方法的拦截器之后,对拦截器是否为空进行了判断:
如果为空,调用AopUtils的invokeJoinpointUsingReflection通过反射直接执行方法即可
如果不为空创建MethodInvocation,具体实现类是ReflectiveMethodInvocation,然后调用proceed执行拦截器链
// 获取当前方法的拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// 校验拦截器链是否为空
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
// 如果为空直接执行目标方法即可
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
} else {
// 创建MethodInvocation,使用的是ReflectiveMethodInvocation类型
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// 执行拦截器链
retVal = invocation.proceed();
}
invokeJoinpointUsingReflection
invokeJoinpointUsingReflection方法通过反射执行目标方法,在AopUtils中实现:
public abstract class AopUtils {
@Nullable
public static Object invokeJoinpointUsingReflection(@Nullable Object target, Method method, Object[] args)
throws Throwable {
// 通过反射执行目标方法
try {
ReflectionUtils.makeAccessible(method);
return method.invoke(target, args);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
catch (IllegalArgumentException ex) {
throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +
method + "] on target [" + target + "]", ex);
}
catch (IllegalAccessException ex) {
throw new AopInvocationException("Could not access method [" + method + "]", ex);
}
}
}
proceed方法执行拦截器链
因为拦截器可以有多个,所以proceed方法是一个递归调用的过程,currentInterceptorIndex记录了当前拦截器的下标:
- 判断currentInterceptorIndex是否与拦截器链的大小一致,如果一致说明已经走到了最后一个拦截器,调用invokeJoinpoint方法执行目标方法即可,可以看到调用了AopUtils的invokeJoinpointUsingReflection通过反射执行目标方法,如果不是最后一个拦截器进入第2步
- 对currentInterceptorIndex++,获取下一个拦截器,判断拦截器是否是InterceptorAndDynamicMethodMatcher类型,如果是获取methodMatcher对目标方法进行匹配:
- 如果与目标方法匹配成功,执行拦截器的invoke方法
- 如果与目标方法匹配不成功,递归调用proceed方法执行下一个拦截器
- 如果拦截器不是InterceptorAndDynamicMethodMatcher类型,直接调用方法拦截器MethodInterceptor的invoke执行拦截器即可
在执行MethodInterceptor方法拦截器的invoke方法时,传入的参数是this,指的是ReflectiveMethodInvocation对象本身,在拦截器方法执行后需要拿到这个对象调用proceed方法继续执行下一个拦截器,可以看到这里使用了责任链模式,对拦截器进行一个个的调用。
public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable {
@Override
@Nullable
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
// 执行方法
return invokeJoinpoint();
}
// 获取下一个拦截器
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// 如果是InterceptorAndDynamicMethodMatcher
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
// 判断方法是否匹配
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// Dynamic matching failed.
// 如果方法不匹配,跳过当前拦截器执行下一个,递归调用
return proceed();
}
}
else {
// 转为MethodInterceptor执行拦截器,注意invoke传入的参数是this,指的是ReflectiveMethodInvocation对象本身,在拦截器的invoke方法中需要拿到这个对象调用proceed方法继续执行下一个拦截器
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
/**
* 通过反射执行目标方法
*/
@Nullable
protected Object invokeJoinpoint() throws Throwable {
return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
}
}
MethodBeforeAdviceInterceptor
以前置通知为例,看一下MethodBeforeAdviceInterceptor拦截器中的invoke方法的执行逻辑:
- 前置通知是在目标方法执行之前执行的方法,所以先调用了invokeAdviceMethod执行了前置通知方法
- 调用MethodInvocation的proceed执行下一个拦截器链,在上一步中可以看到调用拦截器时传入的是this,this指向ReflectiveMethodInvocation,所以会继续执行到它的proceed方法,继续下一个拦截器的执行
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
// 先执行通知方法,在AspectJMethodBeforeAdvice中实现
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
// 执行拦截器链,这里调用的是MethodInvocation的proceed方法,会再次进入到ReflectiveMethodInvocation的proceed方法中
return mi.proceed();
}
}
// AspectJMethodBeforeAdvice
public class AspectJMethodBeforeAdvice extends AbstractAspectJAdvice implements MethodBeforeAdvice, Serializable {
@Override
public void before(Method method, Object[] args, @Nullable Object target) throws Throwable {
// 执行通知方法
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
AspectJAroundAdvice
再以环绕通知为例,看一下环绕通知的执行逻辑,AspectJAroundAdvice实现了MethodInterceptor接口,所以它本身就是一个拦截器,在invoke方法中它调用了invokeAdviceMethod执行通知方法,并将ReflectiveMethodInvocation转换为ProceedingJoinPoint,在环绕通知中通过ProceedingJoinPoint调用proceed方法执行下一个拦截器:
public class AspectJAroundAdvice extends AbstractAspectJAdvice implements MethodInterceptor, Serializable {
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
if (!(mi instanceof ProxyMethodInvocation)) {
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
}
// mi是上一步中传入的ReflectiveMethodInvocation,这里将其转换为ProxyMethodInvocation
ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
// 将ProxyMethodInvocation转为ProceedingJoinPoint
ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
JoinPointMatch jpm = getJoinPointMatch(pmi);
// 执行通知方法
return invokeAdviceMethod(pjp, jpm, null, null);
}
}
@SuppressWarnings("serial")
public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedenceInformation, Serializable {
/**
* 执行通知方法
*/
protected Object invokeAdviceMethod(JoinPoint jp, @Nullable JoinPointMatch jpMatch,
@Nullable Object returnValue, @Nullable Throwable t) throws Throwable {
// 通过给定的参数执行通知方法
return invokeAdviceMethodWithGivenArgs(argBinding(jp, jpMatch, returnValue, t));
}
/**
* 通过给定的参数执行通知方法
*/
protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
Object[] actualArgs = args;
if (this.aspectJAdviceMethod.getParameterCount() == 0) {
actualArgs = null;
}
try {
ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
// 这里执行了通知方法,接下来会进入到定义的环绕通知方法中
return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
}
catch (IllegalArgumentException ex) {
throw new AopInvocationException("Mismatch on arguments to advice method [" +
this.aspectJAdviceMethod + "]; pointcut expression [" +
this.pointcut.getPointcutExpression() + "]", ex);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
假设定义了如下的环绕通知,在环绕通知方法被执行时,会进入到logAroudAdvice方法中,可以看到先打印了方法执行前的日志,然后调用了ProceedingJoinPoint的proceed方法执行拦截器链,上一步可知ProceedingJoinPoint是MethodInvocation转换而来,所以又会进入到ReflectiveMethodInvocation的proceed方法执行下一个拦截器链,待所有的拦截器执行完毕后proceed方法也就结束,然后执行了printAfterLog打印方法执行后的日志:
/**
* 通知Advice,这里使用了环绕通知
* @param joinPoint 连接点
* @return
* @throws Throwable
*/
@Around("logPoiontcut()") // 引用切点
public Object logAroudAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
// 方法执行前的日志打印
printBeforeLog(joinPoint);
// 执行拦截器链
Object returnValue = joinPoint.proceed();
// 方法执行后的日志打印
printAfterLog(returnValue);
return returnValue;
}
总结
方法拦截器链的执行流程图
AOP总结
参考
Spring版本:5.2.5.RELEASE
【Spring】AOP实现原理(三):创建代理的更多相关文章
- Spring AOP 源码分析 - 创建代理对象
1.简介 在上一篇文章中,我分析了 Spring 是如何为目标 bean 筛选合适的通知器的.现在通知器选好了,接下来就要通过代理的方式将通知器(Advisor)所持有的通知(Advice)织入到 b ...
- 循序渐进之Spring AOP(1) - 原理
AOP全称是Aspect Oriented Programing,通常译为面向切面编程.利用AOP可以对面向对象编程做很好的补充. 用生活中的改装车比喻,工厂用面向对象的方法制造好汽车后,车主往往有些 ...
- Spring框架系列(10) - Spring AOP实现原理详解之AOP代理的创建
上文我们介绍了Spring AOP原理解析的切面实现过程(将切面类的所有切面方法根据使用的注解生成对应Advice,并将Advice连同切入点匹配器和切面类等信息一并封装到Advisor).本文在此基 ...
- Spring框架系列(12) - Spring AOP实现原理详解之JDK代理实现
上文我们学习了SpringAOP Cglib动态代理的实现,本文主要是SpringAOP JDK动态代理的案例和实现部分.@pdai Spring框架系列(12) - Spring AOP实现原理详解 ...
- Spring AOP学习笔记04:AOP核心实现之创建代理
上文中,我们分析了对所有增强器的获取以及获取匹配的增强器,在本文中我们就来分析一下Spring AOP中另一部分核心逻辑--代理的创建.这部分逻辑的入口是在wrapIfNecessary()方法中紧接 ...
- Spring框架系列(11) - Spring AOP实现原理详解之Cglib代理实现
我们在前文中已经介绍了SpringAOP的切面实现和创建动态代理的过程,那么动态代理是如何工作的呢?本文主要介绍Cglib动态代理的案例和SpringAOP实现的原理.@pdai Spring框架系列 ...
- spring AOP底层原理实现——jdk动态代理
spring AOP底层原理实现——jdk动态代理
- 【Spring】Spring AOP实现原理
Spring AOP实现原理 在之前的一文中介绍过Spring AOP的功能使用,但是没有深究AOP的实现原理,今天正好看到几篇好文,于是就自己整理了一下AOP实现的几种方式,同时把代理模式相关知识也 ...
- Spring AOP 实现原理
什么是AOP AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善.OOP引入 ...
- Spring AOP底层原理
------------------siwuxie095 Spring AOP 底层原理 AOP 即 Aspect Or ...
随机推荐
- c++对c的拓展_常量引用
常量引用:不能通过引用去修改引用所指向的内容 const int &ref =val; // const int *const ref =&val; 注意:可引用常量 (普通引用无法 ...
- springboot集成spring security安全框架入门篇
一. :spring security的简介 Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架.它提供了一组可以在Spring应用上下 ...
- 基于Apache Hudi在Google云构建数据湖平台
自从计算机出现以来,我们一直在尝试寻找计算机存储一些信息的方法,存储在计算机上的信息(也称为数据)有多种形式,数据变得如此重要,以至于信息现在已成为触手可及的商品.多年来数据以多种方式存储在计算机中, ...
- 在非k8s 环境下 的应用 使用 Dapr Sidekick for .NET
在k8s 环境下,通过Operator 可以管理Dapr sidecar, 在虚拟机环境下,我们也是非常需要这样的一个管理组件,类似下图:在这张图片中,在上图左面,我们看到了"dapr.ex ...
- HTML5+JavaScript+MUI 毕业答辩常见问题
问题1:HTML5前端开发环境有哪些? HTML5网页前端开发,实际也是HTML网页开发,HTML5知识万维网的核心语言.标准通用标记语言下的一个应用超文本标记语言(HTML)的第五次重大修改的第五次 ...
- 2022.02.20 SA
2022.02.20 SA 如果我还能看见明天黎明,如果我还能再爬起来,我仍会走我的路,哪怕这条路已经荒废许久,也许我们无法拥有感情,我们甚至无法像个正常人一样接受太阳的洗礼,但是我依然会执行我的条约 ...
- 苞米面 C++ 模板库 介绍
苞米面 C++ 模板库 简介 苞米面 C++ 模板库,无需编译,直接包含头文件就可以. 所有模板类和算法都包含在 bmm 名字空间里,例如: bmm::recent. 需要 C++ 编译器,支持 C+ ...
- baiyang网站二代域名及短链接
http://985.so/wesv https://cloud.tencent.com/developer/column/93900
- 用 GraphScope 像 NetworkX 一样做图分析
NetworkX 是 Python 上最常用的图分析包,GraphScoep 兼容 NetworkX 接口.本文中我们将分享如何用 GraphScope 像 NetworkX 一样在(大)图上进行分析 ...
- 【Azure Developer】使用 CURL 获取 Key Vault 中 Secrets 中的值
问题描述 在使用CURL通过REST API获取Azure Key Vaualt的Secrets值,提示Missing Token, 问如何来生成正确的Token呢? # curl 命令 curl - ...