Spring中AOP相关源码解析 (3)

public interface Pointcut {
//类过滤器 用于确定类对象是否匹配 只有当类对象匹配后才进行方法的匹配
ClassFilter getClassFilter();

//方法匹配器 用于确定具体哪一些方法需要被增强。 MethodMatcher getMethodMatcher(); //生成一个pointcut对象实例 Pointcut TRUE = TruePointcut.INSTANCE;

}

上面我们可以看到实际上就是通过ClassFilter和MethodMatcher相互配合来实现的,具体的实现过程会因为实现方式大同小异。其中实现方式包括比如正则匹配,AspectJ匹配等,在我们之前的手写系列中就是通过正则来进行匹配的,这里匹配的实现不深入探讨。 通过上面的逻辑便可以确定好增强该类会用到哪些advisor。 #### createProxy 当确定好需要用到的advisor和其顺序后就开始进行创建代理对象了。创建代理对象的方法由前面提到的```wrapIfNecessary```来调用```createProxy```方法实现。 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); for (Advisor advisor : advisors) { proxyFactory.addAdvisor(advisor); } proxyFactory.setTargetSource(targetSource); customizeProxyFactory(proxyFactory); proxyFactory.setFrozen(this.freezeProxy); if (advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } return proxyFactory.getProxy(getProxyClassLoader()); } 创建实际上市代理通过代理工厂类(ProxyFactory)实现的。 ##### JDK代理还是cglib 在创建代理对象时需要确定使用JDK代理还是cglib代理,前面有提到过如果在配置文件中配置了```proxy-target-class="true"```的话那么就只会使用cglib进行代理。但是如果没有配置的话则需要通过实际情况来决定是JDK代理还是cglib。 而除了```proxy-target-class```外,我们实际上还可以配置一个属性```optimize```,该属性默认值为false,如果我们将其置为true那么就表示允许spring对代理生成策略进行优化,意思就是如果该类有接口,就代理接口(使用JDK代理);如果没有接口,就代理类(使用CGLIB代理)。而不是像如果只配置proxyTargetClass=true时强制代理类,而不去考虑代理接口的方式。 综上在spring中使用代理方式的策略如下: - 如果没有配置```optimize```和```proxy-target-class```并且该类实现了接口,那么使用JDK动态代理。 - 如果没有配置```optimize```和```proxy-target-class```并且该类没有实现接口,那么使用cglib动态代理。 - 如果配置了```optimize```和```proxy-target-class```并且该类实现了接口,那么使用JDK动态代理。 - 如果配置了```optimize```和```proxy-target-class```并且该类没有实现接口,那么使用cglib动态代理。 实现代码如下: 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()) { return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); } } 现在已经取到了创建代理对象的策略和目标对象,就可以直接创建代理对象了。如果对这放面有兴趣的可以自行搜索。 创建好代理对象之后使用代理对象替代之前创建好的对象,那么在使用的时候就会调用增强后的方法完成功能。 #### 多个advisor如何确定顺序 在实际开发过程中,可能会存在一个方法被多个advisor增强,可能有的在方法执行前增强有的在方法执行后进行增强。那么在spring中如何确定每一个增强方法的调用时机保证不会出问题的呢? 在手写aop系列中有讲过这个问题,当时我们是通过[责任链模式](https://www.runoob.com/design-pattern/chain-of-responsibility-pattern.html)来解决这个问题。实际上spring中就是通过责任链模式来解决该问题的。 在```JdkDynamicAopProxy```的```invoke```方法中,会通过getInterceptorsAndDynamicInterceptionAdvice方法来获取增强当前调用方法的所有advisor的chain,但是需要注意的是这个chain并不是根据实际应该的执行顺序排列的。仅仅只是所有会被执行的增强方法的集合。

List

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wppyfg.html