JdkDynamicAopProxy
下面是生成代理对象的代码:
// 获取代理对象 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); }
我们再来看看当我们调用目标对象的方法时候,就会来调用 JdkDynamicAopProxy#invoke
方法来实现代理对象。其实核心的原理就是生成了一个代理类,然后去查找关联的 MethodInterceptor
r然后在代理方法中去把这些串起来实现代理。下面我们来看看 inovke
的具体实现:
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)) { // The target does not implement the equals(Object) method itself. // 目标没有实现自己的 equals 方法 return equals(args[0]); } else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { // The target does not implement the hashCode() method itself. // 目标没有实现自己的 hashCode 方法 return hashCode(); } else if (method.getDeclaringClass() == DecoratingProxy.class) { // There is only getDecoratedClass() declared -> dispatch to proxy config. return AopProxyUtils.ultimateTargetClass(this.advised); } else if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) { // Service invocations on ProxyConfig with the proxy config... // 根据代理对象的配置调用服务,如果是Advised接口的实现类,则直接调用 return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); } Object retVal; if (this.advised.exposeProxy) { // Make invocation available if necessary. oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } // Get as late as possible to minimize the time we "own" the target, // in case it comes from a pool. // 有可能为null.尽可能减少拥有目标对象的时间,在这种情况下对象来自于对象池 target = targetSource.getTarget(); Class<?> targetClass = (target != null ? target.getClass() : null); // Get the interception chain for this method. // 获得这个方法的拦截器链 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); // Check whether we have any advice. If we don't, we can fallback on direct // reflective invocation of the target, and avoid creating a MethodInvocation. // 如果没有拦截器链,则直接调用目标对象 if (chain.isEmpty()) { // We can skip creating a MethodInvocation: just invoke the target directly // Note that the final invoker must be an InvokerInterceptor so we know it does // nothing but a reflective operation on the target, and no hot swapping or fancy proxying. Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); } else { // We need to create a method invocation... // 构造一个方法调用 MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); // Proceed to the joinpoint through the interceptor chain. // 调用连接点的拦截器链 retVal = invocation.proceed(); } // Massage return value if necessary. Class<?> returnType = method.getReturnType(); if (retVal != null && retVal == target && returnType != Object.class && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { // Special case: it returned "this" and the return type of the method // is type-compatible. Note that we can't help if the target sets // a reference to itself in another returned object. 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. targetSource.releaseTarget(target); } if (setProxyContext) { // Restore old proxy. // 保存旧的代理对象 AopContext.setCurrentProxy(oldProxy); } } }
总结一下: 这个过程其实可以分为三步:
- 获取原始对象和原始对象的类型,原始对象再
targetSource
中获取到target
, 然后再通过target
获取targetClass
- 通过当前对象的
ProxyFactory
所添加的并匹配的Advisor
封装成MethodInterceptor
的拦截器链chain
- 如果chain为空,则直接执行target对应的当前方法
- 如果chain不为空,则会依次执行chain中的MethodInterceptor。 执行的顺序,会按照通知的设定执行,如果存在相同类型的通知,会按照排序进行执行。
ObjenesisCglibAopProxy
gclib 的代理过程和 jdk 代理很多类似目前我就不再这里详细描述,下面是 gclib 代理对象创建的过程:
- 创建Enhancer
- 设置Enhancer的superClass为通过ProxyFactory.setTarget()所设置的对象的类
- 设置Enhancer的interfaces为通过ProxyFactory.addInterface()所添加的接口,以及SpringProxy、Advised接口
- 设置Enhancer的Callbacks为DynamicAdvisedInterceptor
- 最后通过Enhancer创建一个代理对象
查看生成的代理类代码
//该设置用于输出cglib动态代理产生的类 System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\class"); //该设置用于输出jdk动态代理产生的类 默认在com/sun/proxy 目录下 System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
Spring Aop 使用方式
通过实现PointcutAdvisor接口
- BeanNameAutoProxyCreator
@Bean public BeanNameAutoProxyCreator creator(){ BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator(); beanNameAutoProxyCreator.setBeanNames("userService"); beanNameAutoProxyCreator.setInterceptorNames("myAdvisor"); return beanNameAutoProxyCreator; }
定义的这个bean,相当于一个“自动代理”器,有了这个Bean之后,可以自动的对setBeanNames中所对应的bean进行代理,代理逻辑为所设置的interceptorNames
- DefaultAdvisorAutoProxyCreator
// 定义了 Advisor 过后 DefaultAdvisorAutoProxyCreator // 回自动去查找 BeanPostProcessor @Bean public DefaultAdvisorAutoProxyCreator creator1(){ DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator(); return creator; }
定义 Advisor
@Component public class MyAdvisor implements PointcutAdvisor { @Override public Pointcut getPointcut() { NameMatchMethodPointcut methodPointcut = new NameMatchMethodPointcut(); methodPointcut.setMappedName("test"); return methodPointcut; } @Override public Advice getAdvice() { return new MethodBeforeAdvice() { @Override public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println("方法执行之前"); } }; } @Override public boolean isPerInstance() { return false; } }
在 AbstractAutoProxyCreator#postProcessAfterInitialization
后置处理器方法执行的时候。
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; } // wrapIfNecessary protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { return bean; } //当前这个 Bean 不用被代理 if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } //1.先判断当前的 bean 是不是要进行AOP,比如当前的Bean的类型是 Pointcut, Advice, Advisor 等那些就不需要 AOP if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } // Create proxy if we have advice. //2.如果匹配到 Advisors 不为 null, 那么进行代理并且返回代理对象 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); if (specificInterceptors != DO_NOT_PROXY) { //需要动态代理 this.advisedBeans.put(cacheKey, Boolean.TRUE); //3. 基于 bean 对象和 advice 创建代理对象 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; }
后面会调到 AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean
然后通过 findEligibleAdvisors
方法查找到所有的 Advisor
。 后面再对 Bean 和 Advisor 进行绑定。
通过@Aspect、@Pointcut、@Before等注解
注解方式实现,再前面概念描述的时候已经提到本处不在详细描述。