Advice通知相关的类
通知包装器
负责将各种非MethodInterceptor类型的通知(Advice)包装为MethodInterceptor类型。
PointCut切入点相关类
MethodMatcher过滤流程:
调用matches(Method method, Class<?> targetClass)方法,验证方法是否匹配
isRuntime方法(动态匹配)是否为true,如果为false,则以第一步的结果为准,否则继续向下
调用matches(Method method, Class<?> targetClass, Object... args)方法继续验证,可以对目标方法传入的参数进行校验。
Advisor顾问
DefaultPointcutAdvisor类:里面定义了2个属性:pointcut和advisor,由使用者指定
IntroductionAdvisor接口:可以给目标类引入更多接口的功能
代理创建过程源码解析
创建代理3大步骤:
1. 创建代理所需参数配置
2. 根据配置获取AopProxy对象
1 2 3 4 AopProxyFactory aopProxyFactory = new DefaultAopProxyFactory(); AopProxy aopProxy = aopProxyFactory.createAopProxy(advisedSupport);
此阶段会根据AdvisedSupport中配置信息,判断具体是采用cglib的方式还是采用jdk动态代理的方式获取代理对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 public class DefaultAopProxyFactory implements AopProxyFactory , Serializable { @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); } } private boolean hasNoUserSuppliedProxyInterfaces (AdvisedSupport config) { Class<?>[] ifcs = config.getProxiedInterfaces(); return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0 ]))); } }
3. 通过AopProxy创建代理对象
AopProxy.getProxy
JdkDynamicAopProxy类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 final class JdkDynamicAopProxy implements AopProxy , InvocationHandler , Serializable { private static final long serialVersionUID = 5531744639992436476L ; private static final Log logger = LogFactory.getLog(JdkDynamicAopProxy.class); private final AdvisedSupport advised; private boolean equalsDefined; private boolean hashCodeDefined; public JdkDynamicAopProxy (AdvisedSupport config) throws AopConfigException { Assert.notNull(config, "AdvisedSupport must not be null" ); if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) { throw new AopConfigException("No advisors and no TargetSource specified" ); } this .advised = config; } @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 ); } private void findDefinedEqualsAndHashCodeMethods (Class<?>[] proxiedInterfaces) { for (Class<?> proxiedInterface : proxiedInterfaces) { Method[] methods = proxiedInterface.getDeclaredMethods(); for (Method method : methods) { if (AopUtils.isEqualsMethod(method)) { this .equalsDefined = true ; } if (AopUtils.isHashCodeMethod(method)) { this .hashCodeDefined = true ; } if (this .equalsDefined && this .hashCodeDefined) { return ; } } } } @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 { if (!this .equalsDefined && AopUtils.isEqualsMethod(method)) { return equals(args[0 ]); } else if (!this .hashCodeDefined && AopUtils.isHashCodeMethod(method)) { return hashCode(); } else if (method.getDeclaringClass() == DecoratingProxy.class) { 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 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()) { targetSource.releaseTarget(target); } if (setProxyContext) { AopContext.setCurrentProxy(oldProxy); } } } ... }
小结
被创建的代理对象默认会实现 SpringProxy,Advised,DecoratingProxy 3个接口
SpringProxy 这个接口中没有任何方法,只是起一个标记作用,用来标记代理对象是使用spring aop创建的
代理对象默认都会实现 Advised 接口,所以可以通过这个接口动态变更代理对象中的通知
DecoratingProxy 接口中定义了一个方法 getDecoratedClass ,用来获取被代理的原始目标对象的类型
CglibAopProxy类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 public Object getProxy (@Nullable ClassLoader classLoader) { try { Class<?> rootClass = this .advised.getTargetClass(); Assert.state(rootClass != null , "Target class must be available for creating a CGLIB proxy" ); Class<?> proxySuperClass = rootClass; if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) { proxySuperClass = rootClass.getSuperclass(); Class<?>[] additionalInterfaces = rootClass.getInterfaces(); for (Class<?> additionalInterface : additionalInterfaces) { this .advised.addInterface(additionalInterface); } } validateClassIfNecessary(proxySuperClass, classLoader); Enhancer enhancer = createEnhancer(); if (classLoader != null ) { enhancer.setClassLoader(classLoader); if (classLoader instanceof SmartClassLoader && ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) { enhancer.setUseCache(false ); } } enhancer.setSuperclass(proxySuperClass); enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this .advised)); enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE); enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader)); Callback[] callbacks = getCallbacks(rootClass); Class<?>[] types = new Class<?>[callbacks.length]; for (int x = 0 ; x < types.length; x++) { types[x] = callbacks[x].getClass(); } enhancer.setCallbackFilter(new ProxyCallbackFilter( this .advised.getConfigurationOnlyCopy(), this .fixedInterceptorMap, this .fixedInterceptorOffset)); enhancer.setCallbackTypes(types); return createProxyClassAndInstance(enhancer, callbacks); } catch (CodeGenerationException | IllegalArgumentException ex) { throw new AopConfigException("Could not generate CGLIB subclass of " + this .advised.getTargetClass() + ": Common causes of this problem include using a final class or a non-visible class" , ex); } catch (Throwable ex) { throw new AopConfigException("Unexpected AOP exception" , ex); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 private Callback[] getCallbacks(Class<?> rootClass) throws Exception { boolean exposeProxy = this .advised.isExposeProxy(); boolean isFrozen = this .advised.isFrozen(); boolean isStatic = this .advised.getTargetSource().isStatic(); Callback aopInterceptor = new DynamicAdvisedInterceptor(this .advised); Callback targetInterceptor; if (exposeProxy) { targetInterceptor = (isStatic ? new StaticUnadvisedExposedInterceptor(this .advised.getTargetSource().getTarget()) : new DynamicUnadvisedExposedInterceptor(this .advised.getTargetSource())); } else { targetInterceptor = (isStatic ? new StaticUnadvisedInterceptor(this .advised.getTargetSource().getTarget()) : new DynamicUnadvisedInterceptor(this .advised.getTargetSource())); } Callback targetDispatcher = (isStatic ? new StaticDispatcher(this .advised.getTargetSource().getTarget()) : new SerializableNoOp()); Callback[] mainCallbacks = new Callback[] { aopInterceptor, targetInterceptor, new SerializableNoOp(), targetDispatcher, this .advisedDispatcher, new EqualsInterceptor(this .advised), new HashCodeInterceptor(this .advised) }; Callback[] callbacks; if (isStatic && isFrozen) { Method[] methods = rootClass.getMethods(); Callback[] fixedCallbacks = new Callback[methods.length]; this .fixedInterceptorMap = new HashMap<>(methods.length); for (int x = 0 ; x < methods.length; x++) { Method method = methods[x]; List<Object> chain = this .advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass); fixedCallbacks[x] = new FixedChainStaticTargetInterceptor( chain, this .advised.getTargetSource().getTarget(), this .advised.getTargetClass()); this .fixedInterceptorMap.put(method, x); } callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length]; System.arraycopy(mainCallbacks, 0 , callbacks, 0 , mainCallbacks.length); System.arraycopy(fixedCallbacks, 0 , callbacks, mainCallbacks.length, fixedCallbacks.length); this .fixedInterceptorOffset = mainCallbacks.length; } else { callbacks = mainCallbacks; } return callbacks; }
DynamicAdvisedInterceptor类 :处理拦截器类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 private static class DynamicAdvisedInterceptor implements MethodInterceptor , Serializable { private final AdvisedSupport advised; public DynamicAdvisedInterceptor (AdvisedSupport advised) { this .advised = advised; } @Override @Nullable public Object intercept (Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { Object oldProxy = null ; boolean setProxyContext = false ; Object target = null ; TargetSource targetSource = this .advised.getTargetSource(); try { 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); Object retVal; if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) { Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); retVal = methodProxy.invoke(target, argsToUse); } else { retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed(); } retVal = processReturnType(proxy, target, method, retVal); return retVal; } finally { if (target != null && !targetSource.isStatic()) { targetSource.releaseTarget(target); } if (setProxyContext) { AopContext.setCurrentProxy(oldProxy); } } } }
方法拦截器链的获取
代理方法的调用过程(拦截器链的执行)
创建完代理对象后,开始使用,在代理对象上执行一些方法调用,此时会依次调用此方法上的所有MethodInterceptor,最终会调用到目标上对应的方法。
ReflectiveMethodInvocation类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 public class ReflectiveMethodInvocation implements ProxyMethodInvocation , Cloneable { protected final Object proxy; protected final Object target; protected final Method method; protected Object[] arguments; private final Class<?> targetClass; protected final List<?> interceptorsAndDynamicMethodMatchers; private int currentInterceptorIndex = -1 ; 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 { if (this .currentInterceptorIndex == this .interceptorsAndDynamicMethodMatchers.size() - 1 ) { return invokeJoinpoint(); } Object interceptorOrInterceptionAdvice = this .interceptorsAndDynamicMethodMatchers.get(++this .currentInterceptorIndex); if (interceptorOrInterceptionAdvice instanceof 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 { return proceed(); } } else { return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this ); } } @Nullable protected Object invokeJoinpoint () throws Throwable { return AopUtils.invokeJoinpointUsingReflection(this .target, this .method, this .arguments); } ... }
创建AOP代理
ProxyFactoryBean创建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 @Configuration public class MainConfig1 { @Bean public Service1 service1 () { return new Service1(); } @Bean public Advisor interceptor1 () { MethodBeforeAdvice advice = new MethodBeforeAdvice() { @Override public void before (Method method, Object[] args, Object target) throws Throwable { System.out.println("准备调用" +method); } }; DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(); advisor.setAdvice(advice); return advisor; } @Bean public MethodInterceptor interceptor2 () { MethodInterceptor methodInterceptor = new MethodInterceptor() { @Override public Object invoke (MethodInvocation invocation) throws Throwable { long starTime = System.nanoTime(); Object result = invocation.proceed(); long endTime = System.nanoTime(); System.out.println(invocation.getMethod() + ",耗时(纳秒):" + (endTime - starTime)); return result; } }; return methodInterceptor; } @Bean public AfterReturningAdvice afterReturningAdvice () { AfterReturningAdvice afterReturningAdvice = new AfterReturningAdvice() { @Override public void afterReturning (@Nullable Object returnValue, Method method, Object[] args, @Nullable Object target) throws Throwable { System.out.println(method + ",执行完毕!" ); } }; return afterReturningAdvice; } @Bean public ProxyFactoryBean service1Proxy () { ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean(); proxyFactoryBean.setTargetName("service1" ); proxyFactoryBean.setInterceptorNames("interceptor*" , "afterReturningAdvice" ); return proxyFactoryBean; } }
ProxyFactoryBean类主要方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 public Object getObject () throws BeansException { initializeAdvisorChain(); if (isSingleton()) { }else { return newPrototypeInstance(); } } private synchronized void initializeAdvisorChain () throws AopConfigException, BeansException { if (this .advisorChainInitialized) { return ; } if (!ObjectUtils.isEmpty(this .interceptorNames)) { for (String name : this .interceptorNames) { if (name.endsWith(GLOBAL_SUFFIX)) { if (!(this .beanFactory instanceof ListableBeanFactory)) { throw new AopConfigException( "Can only use global advisors or interceptors with a ListableBeanFactory" ); } addGlobalAdvisors((ListableBeanFactory) this .beanFactory, name.substring(0 , name.length() - GLOBAL_SUFFIX.length())); } else { Object advice; if (this .singleton || this .beanFactory.isSingleton(name)) { advice = this .beanFactory.getBean(name); } else { advice = new PrototypePlaceholderAdvisor(name); } addAdvisorOnChainCreation(advice); } } } this .advisorChainInitialized = true ; }
AspectJProxyFactory创建
@Aspect
标注的类上,这个类中,可以通过通过 @Pointcut
来定义切入点,可以通过 @Before
、 @Around
、@After
、@AfterRunning
、@AfterThrowing
标注在方法上来定义通知,定义好了之后,将@Aspect
标注的这个类交给 AspectJProxyFactory
来解析生成 Advisor 链,进而结合目标对象一起来生成代理对象.
@Pointcut的12种用法
表达式标签(10种):
execution:用于匹配方法执行的连接点
within:用于匹配指定类型内的方法执行
this:用于匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口也类型匹配
target:用于匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配
args:用于匹配当前执行的方法传入的参数为指定类型的执行方法
@within:用于匹配所有持有指定注解类型内的方法
@target:用于匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解
@args:用于匹配当前执行的方法传入的参数所属的类 持有指定注解的
@annotation:用于匹配当前执行方法持有指定注解的
bean:Spring AOP扩展的,AspectJ没有对于指示符,用于匹配特定名称的Bean对象的执行方法
execution格式
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)
带?号的为可选项
modifier-pattern? 修饰符匹配,如public 表示匹配公有方法
ret-type-pattern 返回值匹配,* 表示任何返回值,全路径的类名等
declaring-type-pattern? 类路径匹配,com.example…IService+代表com.example包及其子包下所有IService接口及子类型的
name-pattern 方法名匹配,* 代表所有,set*,代表以set开头的所有方法
(param-pattern) 参数匹配,(…)代表所有参数;(*,String)代表第一个参数为任何值,第二个为String类型;(…,String)代表最后一个参数是String类型
throws-pattern? 异常类型匹配
表达式标签
判断的对象
判断规则 **(x****:指表达式中指定的类型****)**
within
target对象
target.getClass().equals(表达式中指定的类型)
this
proxy对象
x.getClass().isAssignableFrom(proxy.getClass());
target
target对象
x.getClass().isAssignableFrom(target.getClass());
@Aspect中5种通知
@Before:前置通知, 在方法执行之前执行
@Aroud:环绕通知, 围绕着方法执行
@After:后置通知, 在方法执行之后执行
@AfterReturning:返回通知, 在方法返回结果之后执行
@AfterThrowing:异常通知, 在方法抛出异常之后
执行顺序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 private static final Comparator<Method> METHOD_COMPARATOR;static { Comparator<Method> adviceKindComparator = new ConvertingComparator<>( new InstanceComparator<>( Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class), (Converter<Method, Annotation>) method -> { AspectJAnnotation<?> ann = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method); return (ann != null ? ann.getAnnotation() : null ); }); Comparator<Method> methodNameComparator = new ConvertingComparator<>(Method::getName); METHOD_COMPARATOR = adviceKindComparator.thenComparing(methodNameComparator); } try { System.out.println("@Around通知start" ); System.out.println("@Before通知!" ); Object retVal = null ; try { try { retVal = mi.proceed(); } catch (Throwable ex) { if (shouldInvokeOnThrowing(ex)) { System.out.println("@AfterThrowing通知!" ); } throw ex; } System.out.println("@AfterReturning通知!" ); } finally { System.out.println("@After通知!" ); } System.out.println("@Around通知end" ); return retVal; } catch (RuntimeException ex) { throw ex; } catch (Exception ex) { if (ReflectionUtils.declaresException(getMethod(), ex.getClass())) { throw ex; } else { throw new UndeclaredThrowableException(ex); } }
thumb_up
本文链接: http://lampkins.gitee.io/2022/02/11/Spring-AOP%E6%A0%B8%E5%BF%83%E6%BA%90%E7%A0%81%E3%80%81%E5%8E%9F%E7%90%86/