JDK动态代理两要素:Proxy+InvocationHandler
CGLB动态代理两要素:Enhancer + MethodInterceptor(Callback)
概念的理解:
- 通知: 通知可以理解增强器, 就是做的额外工作.
- 连接点: 可以允许切面插入的点, 这个点可以是方法调用时, 抛出异常时等.
- 切点: 并不是所有的连接点都需要被切面插入, 切点就是定义哪些连接点可以插入切面.
组件的理解:
AOP联盟规范定义组件
注意一点:这里的MethodInterceptor区别于上文提到的org.springframework.cglib.proxy.MethodInterceptor不要混了。
spring定义组件
分为
- IntroductionAdvisor: 引介增强,在不修改某个类的情况下, 让其具备某接口的功能。
- PointcutAdvisor: 与切点有关的Advisor
实现类AdvisedSupport:从其两个属性上,真切看出其封装了 Advisor 与 TargetSource
- TargetSource targetSource = EMPTY_TARGET_SOURCE; 表示目标对象
- private List advisors = new ArrayList(); 存储Advisor
- 分JDK代理(JdkDynamicAopProxy)
- Cglib代理(CglibAopProxy)
- ProxyConfig: 提供aop配置属性。
- AdvisedSupport:继承ProxyConfig,实现了Advised接口。封装通知(Advise)和TargetSource,并提供对他们的操作
- ProxyCreatorSupport: 包含AopProxyFactory,AopProxyFactory策略工厂提供对JdkDynamicAopProxy与CglibAopProxy的创建
- 首先他是一个(BeanPostProcessor)InstantiationAwareBeanPostProcessor 所以他会在spring的Bean生产线createBean()过程中被执行。在BeanDefinition创建Bean的过程中进行拦截,根据要求创建出代理对象。
- Aware: 可以获取到BeanFactory仓库, 与BeanClassLoader加载器。
- ProxyCreatorSupport,继承了创建代理的功能。
- 《1》定义的解析:
- 《2》代理的创建:
- 《3》代理的执行:
代理的生成过程:
我们还是以springboot环境下的AOP实现来讲讲AOP的过程.
@Override public void registerBeanDefinitions( AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {//注入AnnotationAwareAspectJAutoProxyCreator扩展器 AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry); AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class); if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) { AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); } if (enableAspectJAutoProxy.getBoolean("exposeProxy")) { AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry); } }
- 是一个BeanPostProcessor,可以拦截Bean创建过程
- 继承了ProxyCreatorSupport具有代理类的创建能力。
postProcessBeforeInstantiation() -->postProcessAfterInstantiation-->postProcessPropertyValues-->postProcessBeforeInitialization()-->postProcessAfterInitialization()
@Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { Object cacheKey = getCacheKey(beanClass, beanName); if (beanName == null || !this.targetSourcedBeans.contains(beanName)) { if (this.advisedBeans.containsKey(cacheKey)) { return null; } if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return null; } } if (beanName != null) { TargetSource targetSource = getCustomTargetSource(beanClass, beanName); if (targetSource != null) { 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; }
(2.1.1)先判断是否应该代理
- isInfrastructureClass(beanClass)如果是AOP基础设施类, 不代理。指的是Advice、Pointcut、Advisor等AOP相关定义类不应该创建代理
- shouldSkip()应该跳过的类,不代理。判断的依据:默认是都不跳过的. 子类可能重写其判断依据.AnnotationAwareAspectJAutoProxyCreator的父类AnnotationAwareAspectJAutoProxyCreator重写了shouldSkip方法(《1》并伴随切面定义的解析)。
/*1.首先查找适于当前Bean的Advisor .通findCandidateAdvisors()去查找 findCandidateAdvisors()会经过两个渠道获取Advisors. > BeanFactoryAdvisorRetrievalHelper.findAdvisorBeans():是从仓库中找实现了Advisor类的Advisor > BeanFactoryAspectJAdvisorsBuilder.buildAspectJAdvisors()会从仓库中取出@Aspect注解的切面类,解析出Advisor 重点说一下其中buildAspectJAdvisors >遍历BeanFactory仓库中的BeanDefinition,根据其类型判断其是否是isAspect(): 判断条件是类是否被@Aspect注释,并且没有被aspectj编译过 >如果是, 根据当前BeanDefinition创建一个(AspectJAdvisorFactory)BeanFactoryAspectInstanceFactory工厂对象. >使用AspectJAdvisorFactory 工厂创建List<Advisor> >上文已经说过Advisor=Advice+Pointcut, Advice 就是对通知的封装(@Before...), Pointcut 是对切点的封装. 小结:这次知道我们定义一个切面类, 被解析什么样子了吧2.判断找到的CandidateAdvisors中有没有当前BeanDefinition,有的话就跳过。*/@Override protected boolean shouldSkip(Class<?> beanClass, String beanName) { // TODO: Consider optimization by caching the list of the aspect names List<Advisor> candidateAdvisors = findCandidateAdvisors(); for (Advisor advisor : candidateAdvisors) { if (advisor instanceof AspectJPointcutAdvisor) { if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) { returntrue; } } } return super.shouldSkip(beanClass, beanName); }
如果有自定义TargetSource ,将当前beanName放入targetSourcedBeans缓存中,直接走创建代理的分支,不会走createBean去创建Bean,这里就是给一个机会。 关于自定义TargetSource这个分支暂时不讲。
if (beanName != null) { TargetSource targetSource = getCustomTargetSource(beanClass, beanName); if (targetSource != null) { 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; } }
- 解析切面定义
- 提供一个机会直接返回代理对象,不走createBean()流水线。自定义TargetSource
- return true ;
- 返回Bean没有做处理
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { 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) { //1.自定义TargetSource,已经进行过代理子类生成 。 不包装直接返回Bean实例 if (beanName != null && this.targetSourcedBeans.contains(beanName)) { return bean; } //2.已经判定不需要代理的, 不代理 if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } //3.isInfrastructureClass(bean.getClass())是基础设施类的不代理 //4.shouldSkip(bean.getClass(), beanName)应该跳过的不代理 if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } // Create proxy if we have advice. Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); if (specificInterceptors != DO_NOT_PROXY) { this.advisedBeans.put(cacheKey, Boolean.TRUE); Object proxy = createProxy( bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } //5.没有具体拦截器的不代理 this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; }
- 自定义TargetSource,已经进行过代理子类生成 。 不包装直接返回Bean实例。()
- 已经判定不需要代理的, 不代理。 直接返回Bean实例
- isInfrastructureClass(bean.getClass())是基础设施类的不代理。 (上文已经提过)
- shouldSkip(bean.getClass(), beanName)应该跳过的不代理 (上文已经提过)
- 没有具体拦截器的不代理
- 有具体Advice的才代理:getAdvicesAndAdvisorsForBean() 的返回不为空的。(Create proxy if we have advice.)
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { List<Advisor> candidateAdvisors = findCandidateAdvisors(); List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; }
-
findCandidateAdvisors: 获取所有Advisor ,前面已经说过。 因为做了缓存此处直接从缓存中取。
- findAdvisorsThatCanApply: 看其传入的参数,candidateAdvisors(所有的候选Advisor), 也就是这个方法肯定就是从所有的候选Advisor找出适合当前Bean
-
extendAdvisors: 允许子类添加advisor
findAdvisorsThatCanApply最终调用AopUtils.findAdvisorsThatCanApply:
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) { if (candidateAdvisors.isEmpty()) { return candidateAdvisors; } List<Advisor> eligibleAdvisors = new LinkedList<Advisor>(); //第一遍 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; }
第一个for循环寻找IntroductionAdvisor(引介增强)类型的advisor,调用AopUtils.canApply
第二遍for循环寻找普通的advisor,调用AopUtils.canApply
- 针对IntroductionAdvisor类型advisor的,只需要校验Advisor的ClassFilter是否匹配当前类
- 针对普通的advisor:(1)首先查看定的类是否在Pointcut的匹配范围内;(2)是的话,再查看是否能匹配此类任意方法,是的话返回true;(3)不能匹配任意方法,便会用反射的方法获取targetClass(被检测类)的全部方法逐一交由Pointcut的MethodMatcher.matches方法进行检测。
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) { Assert.notNull(pc, "Pointcut must not be null"); if (!pc.getClassFilter().matches(targetClass)) { return false; } //是否配置任意方法 MethodMatcher methodMatcher = pc.getMethodMatcher(); if (methodMatcher == MethodMatcher.TRUE) { // No need to iterate the methods if we're matching any method anyway... return true; } IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null; if (methodMatcher instanceof IntroductionAwareMethodMatcher) { introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher; } //逐一排查 Set<Class<?>> classes = new LinkedHashSet<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass)); classes.add(targetClass); for (Class<?> clazz : classes) { Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz); for (Method method : methods) { if ((introductionAwareMethodMatcher != null && introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) || methodMatcher.matches(method, targetClass)) { return true; } } } returnfalse; }
在getAdvicesAndAdvisorsForBean返回advisors不为null后,可以创建代理。
protected Object createProxy( Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) { ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.copyFrom(this); if (!proxyFactory.isProxyTargetClass()) { if (shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true); } else { 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()); }
- 首先创建ProxyFactory 工厂,从AbstractAutoProxyCreator复制代理属性,因为AbstractAutoProxyCreator继承了ProxyConfig,所以本身也是一个代理配置类。
- 判断其是基于类代理, 还是基于接口代理。如果基于接口代理,获取接口,并设置到ProxyFactory 。
- buildAdvisors()方法,整合getAdvicesAndAdvisorsForBean找的advisors 与AbstractAutoProxyCreator. interceptorNames属性可能设置的增强器,统一包装成Advisor类型数组,设置到ProxyFactory 。并且AbstractAutoProxyCreator. interceptorNames属性设置的增强器在前。
- customizeProxyFactory(proxyFactory); 子类可以继续处理ProxyFactory
- 设置ProxyFactory的Frozen属性
- setPreFiltered设置ProxyFactory 的preFiltered
- getProxy 返回代理对象
@Override public Object getProxy(ClassLoader classLoader) { if (logger.isDebugEnabled()) { logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource()); } Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true); findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); }
InvocationHandler 此时就是JdkDynamicAopProxy,同时JdkDynamicAopProxy封装了advised。这样完美的把advised与JDK动态代理联系在了一起。
(省略部分源码,直奔主题)
// Configure CGLIB Enhancer... Enhancer enhancer = createEnhancer(); Callback[] callbacks = getCallbacks(rootClass); enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised)); return createProxyClassAndInstance(enhancer, callbacks); }
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
接下来就是在内存中生成一个新的字节码CGLB代理类***$$FastClassByCGLIB$$29e52466,并生成真实代理对象了。
总结