在上一篇 重拾-Spring AOP
中咱们会发现 Spring AOP 是经过类 ProxyFactoryBean
建立代理对象,其有个缺陷就是只能代理一个目标对象 bean, 当代理目标类过多时,配置文件臃肿不方便管理维护,所以 Spring 提供了可以实现自动建立代理的类 BeanNameAutoProxyCreator
, DefaultAdvisorAutoProxyCreator
;下面咱们看下两者是如何实现自动代理的。java
BeanNameAutoProxyCreator
是经过判断当前 bean name 是否匹配,只有匹配的 bean 才会建立代理。
<bean id="userService" class="org.springframework.aop.UserServiceImpl" /> <bean id="demoService" class="org.springframework.aop.DemoServiceImpl" /> <bean id="userBeforeAdvice" class="org.springframework.aop.UserBeforeAdvice" /> <bean id="userAfterAdvice" class="org.springframework.aop.UserAfterAdvice" /> <bean id="beanNameAutoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <!-- 配置要代理的 bean --> <property name="beanNames"> <list> <value>userService</value> <value>demoService</value> </list> </property> <!-- 配置 interceptor, advice, advisor --> <property name="interceptorNames"> <list> <value>userAfterAdvice</value> <value>userBeforeAdvice</value> </list> </property> </bean>
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/org/springframework/aop/aop.xml"); UserService userService = (UserService) ctx.getBean("userService"); userService.say(); DemoService demoService = (DemoService) ctx.getBean("demoService"); demoService.demo();
do before advice .... do say method do after return advice .... do before advice .... do demo. do after return advice ....
如上图 BeanNameAutoProxyCreator
类结构能够看出,其实现了接口 BeanPostProcessor
; 那么咱们能够大概猜想出其自动代理的实现原理与自动注入相似,都是在 bean 实例化后进行特殊的处理,下面就让咱们看下源码验证下吧。正则表达式
public Object postProcessAfterInitialization(Object bean, String name) throws BeansException { // Check for special cases. We don't want to try to autoproxy a part of the autoproxying // infrastructure, lest we get a stack overflow. if (isInfrastructureClass(bean, name) || shouldSkip(bean, name)) { logger.debug("Did not attempt to autoproxy infrastructure class '" + bean.getClass() + "'"); return bean; } TargetSource targetSource = getTargetSource(bean, name); Object[] specificInterceptors = getInterceptorsAndAdvisorsForBean(bean, name); // proxy if we have advice or if a TargetSourceCreator wants to do some // fancy stuff such as pooling if (specificInterceptors != DO_NOT_PROXY || !(targetSource instanceof SingletonTargetSource)) { // handle prototypes correctly // 获取容器中配置的 advisors Advisor[] commonInterceptors = resolveInterceptorNames(); List allInterceptors = new ArrayList(); if (specificInterceptors != null) { allInterceptors.addAll(Arrays.asList(specificInterceptors)); if (commonInterceptors != null) { if (this.applyCommonInterceptorsFirst) { allInterceptors.addAll(0, Arrays.asList(commonInterceptors)); } else { allInterceptors.addAll(Arrays.asList(commonInterceptors)); } } } if (logger.isInfoEnabled()) { int nrOfCommonInterceptors = commonInterceptors != null ? commonInterceptors.length : 0; int nrOfSpecificInterceptors = specificInterceptors != null ? specificInterceptors.length : 0; logger.info("Creating implicit proxy for bean '" + name + "' with " + nrOfCommonInterceptors + " common interceptors and " + nrOfSpecificInterceptors + " specific interceptors"); } ProxyFactory proxyFactory = new ProxyFactory(); // copy our properties (proxyTargetClass) inherited from ProxyConfig proxyFactory.copyFrom(this); if (!getProxyTargetClass()) { // Must allow for introductions; can't just set interfaces to // the target's interfaces only. // 添加设置代理的接口 Class[] targetsInterfaces = AopUtils.getAllInterfaces(bean); for (int i = 0; i < targetsInterfaces.length; i++) { proxyFactory.addInterface(targetsInterfaces[i]); } } for (Iterator it = allInterceptors.iterator(); it.hasNext();) { Advisor advisor = GlobalAdvisorAdapterRegistry.getInstance().wrap(it.next()); // 添加 advisor proxyFactory.addAdvisor(advisor); } proxyFactory.setTargetSource(getTargetSource(bean, name)); // 建立代理对象,依旧采用的 jdk 动态代理; 由于上面设置了代理的 interface return proxyFactory.getProxy(); } else { return bean; } }
protected Object[] getInterceptorsAndAdvisorsForBean(Object bean, String beanName) { if (this.beanNames != null) { // bean name 包含在配置的名称列表中,说明须要代理 if (this.beanNames.contains(beanName)) { return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS; } for (Iterator it = this.beanNames.iterator(); it.hasNext();) { String mappedName = (String) it.next(); // bean name 匹配通配符,说明须要代理 if (isMatch(beanName, mappedName)) { return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS; } } } // 说明 bean 不须要代理 return DO_NOT_PROXY; }
protected boolean isMatch(String beanName, String mappedName) { // bean name 匹配通配符 return (mappedName.endsWith("*") && beanName.startsWith(mappedName.substring(0, mappedName.length() - 1))) || (mappedName.startsWith("*") && beanName.endsWith(mappedName.substring(1, mappedName.length()))); }
从 BeanNameAutoProxyCreator
的源码大概总结其自动代理流程:spring
DefaultAdvisorAutoProxyCreator
会搜索BeanFactory
容器内部全部可用的Advisor
; 并为容器中匹配的 bean 建立代理。 在上一篇重拾-Spring AOP
中咱们知道 Spring AOP 会默认建立实例为DefaultPointcutAdvisor
的Advisor
; 那么在分析DefaultAdvisorAutoProxyCreator
以前,咱们看下 Spring AOP 还为咱们提供了哪些内置的Advisor
。
NameMatchMethodPointcutAdvisor
是按 method name 匹配,只有当目标类执行方法匹配的时候,才会执行Advice
public class NameMatchMethodPointcut extends StaticMethodMatcherPointcut { // 配置拦截的 method name private String[] mappedNames = new String[0]; public boolean matches(Method m, Class targetClass) { for (int i = 0; i<this.mappedNames.length; i++) { String mappedName = this.mappedNames[i]; // 目标方法是否与配置的 method name 相等;或者匹配通配符 if (mappedName.equals(m.getName()) || isMatch(m.getName(), mappedName)) { return true; } } return false; } // 是否以 * 开头或结束并匹配 protected boolean isMatch(String methodName, String mappedName) { return (mappedName.endsWith("*") && methodName.startsWith(mappedName.substring(0, mappedName.length() - 1))) || (mappedName.startsWith("*") && methodName.endsWith(mappedName.substring(1, mappedName.length()))); } }
RegexpMethodPointcutAdvisor
是按照正则表达式匹配方法,可以精肯定位到须要拦截的方法。
public class RegexpMethodPointcut extends StaticMethodMatcherPointcut implements ClassFilter { public boolean matches(Method m, Class targetClass) { // TODO use target class here? // 拼接表达式 String patt = m.getDeclaringClass().getName() + "." + m.getName(); for (int i = 0; i < this.compiledPatterns.length; i++) { // 正则匹配 boolean matched = this.matcher.matches(patt, this.compiledPatterns[i]); if (logger.isDebugEnabled()) { logger.debug("Candidate is: '" + patt + "'; pattern is " + this.compiledPatterns[i].getPattern() + "; matched=" + matched); } if (matched) { return true; } } return false; } public boolean matches(Class clazz) { // TODO do with regexp return true; } public ClassFilter getClassFilter() { return this; } }
<beans> <bean id="userService" class="org.springframework.aop.UserServiceImpl" /> <bean id="demoService" class="org.springframework.aop.DemoServiceImpl" /> <bean id="userBeforeAdvice" class="org.springframework.aop.UserBeforeAdvice" /> <bean id="userAfterAdvice" class="org.springframework.aop.UserAfterAdvice" /> <!-- 按方法名称匹配 --> <bean id="nameMatchMethodPointcutAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor"> <property name="mappedNames"> <!-- 匹配 save 开头的方法 --> <value>save*</value> </property> <property name="advice"> <ref bean="userBeforeAdvice" /> </property> </bean> <bean id="regexpMethodPointcutAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> <property name="pattern"> <!-- 匹配以 del 开头的方法 --> <value>org.springframework.aop.*.del*.*</value> </property> <property name="advice"> <ref bean="userAfterAdvice" /> </property> </bean> <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" /> </beans>
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/org/springframework/aop/aop.xml"); UserService userService = (UserService) ctx.getBean("userService"); userService.saveUser(); userService.delUser(); DemoService demoService = (DemoService) ctx.getBean("demoService"); demoService.saveDemo(); demoService.delDemo();
do before advice .... do save user ...... do del user ...... do after return advice .... do before advice .... do save demo ...... do del demo ...... do after return advice ....
从测试结果能够看出,经过配置不一样Advisor
匹配不一样的Method
采用相应的Advice
进行处理。
从上图 DefaultAdvisorAutoProxyCreator
类结构,咱们知道其实现与 BeanNameAutoProxyCreator
相似;都是经过实现接口 BeanPostProcessor
在 bean 完成实例化后进行自动代理处理。app
因 DefaultAdvisorAutoProxyCreator
和 BeanNameAutoProxyCreator
都继承了类 AbstractAutoProxyCreator
,因此从源码中咱们能够发现两者都重写了方法 getInterceptorsAndAdvisorsForBean
,也就是在获取当前 bean 所匹配的 Advisor
逻辑不同以外其余处理一致; 那么下面针对 DefaultAdvisorAutoProxyCreator
的实现咱们主要看下方法 getInterceptorsAndAdvisorsForBean
的处理。源码分析
protected Object[] getInterceptorsAndAdvisorsForBean(Object bean, String name) { // 查找与当前 bean 匹配的 advisor List advices = findEligibleAdvisors(bean.getClass()); if (advices.isEmpty()) { return DO_NOT_PROXY; } // 对 advisor 集合排序 advices = sortAdvisors(advices); return advices.toArray(); }
protected List findEligibleAdvisors(Class clazz) { // 查找当前容器中全部定义的 advisor List candidateAdvice = findCandidateAdvisors(); List eligibleAdvice = new LinkedList(); for (int i = 0; i < candidateAdvice.size(); i++) { // Sun, give me generics, please! Advisor candidate = (Advisor) candidateAdvice.get(i); // 判断 bean 是否能够应用 advisor if (AopUtils.canApply(candidate, clazz, null)) { // 将 advisor 添加到匹配的集合中 eligibleAdvice.add(candidate); logger.info("Candidate Advice [" + candidate + "] accepted for class [" + clazz.getName() + "]"); } else { logger.info("Candidate Advice [" + candidate + "] rejected for class [" + clazz.getName() + "]"); } } return eligibleAdvice; }
protected List findCandidateAdvisors() { if (!(getBeanFactory() instanceof ListableBeanFactory)) { throw new IllegalStateException("Cannot use DefaultAdvisorAutoProxyCreator without a ListableBeanFactory"); } ListableBeanFactory owningFactory = (ListableBeanFactory) getBeanFactory(); // 从容器中查找全部 bean 定义 type 为 Advisor 的 bean name String[] adviceNames = BeanFactoryUtils.beanNamesIncludingAncestors(owningFactory, Advisor.class); List candidateAdvisors = new LinkedList(); for (int i = 0; i < adviceNames.length; i++) { String name = adviceNames[i]; if (!this.usePrefix || name.startsWith(this.advisorBeanNamePrefix)) { // 获取 advisor 实例 Advisor advisor = (Advisor) owningFactory.getBean(name); candidateAdvisors.add(advisor); } } return candidateAdvisors; }
public static boolean canApply(Advisor advisor, Class targetClass, Class[] proxyInterfaces) { if (advisor instanceof IntroductionAdvisor) { return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass); } else if (advisor instanceof PointcutAdvisor) { PointcutAdvisor pca = (PointcutAdvisor) advisor; // 经过 advisor 的 pointcut 判断 bean 是否匹配 return canApply(pca.getPointcut(), targetClass, proxyInterfaces); } else { // It doesn't have a pointcut so we assume it applies return true; } } public static boolean canApply(Pointcut pc, Class targetClass, Class[] proxyInterfaces) { // 类是否匹配 if (!pc.getClassFilter().matches(targetClass)) { return false; } // 判断类中的 method 是否匹配 // 获取类下全部的method Method[] methods = targetClass.getMethods(); for (int i = 0; i < methods.length; i++) { Method m = methods[i]; // If we're looking only at interfaces and this method // isn't on any of them, skip it if (proxyInterfaces != null && !methodIsOnOneOfTheseInterfaces(m, proxyInterfaces)) { continue; } // 执行 pointcut 的 method match if (pc.getMethodMatcher().matches(m, targetClass)) return true; } return false; }
从 DefaultAdvisorAutoProxyCreator
的源码分析,可知其自动代理流程大概以下:post
Advisor
实例Advisor
从 BeanNameAutoProxyCreator
, DefaultAdvisorAutoProxyCreator
两者的实现能够看出其相同点测试
BeanPostProcessor
的实现Advisor
,后在建立代理对象两者的不一样点在于:this
Advisor
内部的 Ponitcut
匹配判断Advisor
是用户配置的,后者是容器中全部匹配的 Advisor