一、接口概述
Advisor:包含AOP通知的基本接口(在连接点采取的操作)和一个确定建议的适用性的过滤器(例如一个切入点)。这个接口不是供Spring用户使用的,而是允许在支持不同类型的通知时具有通用性。Spring AOP基于通过方法拦截的环绕通知传递,符合AOP联盟拦截API。Advisor接口支持不同类型的建议,如之前和之后的通知,不需要使用拦截实现。
PointcutAdvisor:由切入点驱动的所有Advisor的超级接口。这几乎涵盖了除introduction advisors以外的所有Advisor。PointcutAdvisor中包含了一个Pointcut成员变量,也就是切点,在加上Advisor接口中的Advice,就形成了一个完整的切面。
StaticMethodMatcherPointcutAdvisor:静态方法匹配器切点定义的切面,默认情况下匹配所有的的目标类。(shiro权限设计就是通过继承该类实现的)。
InstantiationModelAwarePointcutAdvisor:该接口有唯一实现类InstantiationModelAwarePointcutAdvisorImpl。该类就是我们通常在项目中通过aspectj注解实现的切面被包装后的Advisor。
AspectJExpressionPointcutAdvisor:用于AspectJ切点表达式定义切点的切面
AbstractPointcutAdvisor:PointcutAdvisor实现的抽象基类,可以为返回特定切入点/通知或可自由配置的切入点/通知的子类
二、spring如何判断bean是否需要被代理
spring在创建完bean后,需要判断是否需要给当前bean创建代理对象。org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory类中的doCreateBean方法后会调用applyBeanPostProcessorsAfterInitialization方法,该方法会调用所有BeanPostProcessor的postProcessAfterInitialization。org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator就是一个BeanPostProcessor,该类的postProcessAfterInitialization会调用wrapIfNecessary方法,即该bean是否需要被包装成代理对象。是否需要代理原则就是该bean有没有与之相关的Advisor,有就代理。
三、spring如何查找所有Advisor源码及如何判断某个bean与之关联的Advisor有哪些
wrapIfNecessary部分源码
// Create proxy if we have advice. //获取bean有关的Advisor 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; }
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { //查找所有的Advisor List<Advisor> candidateAdvisors = findCandidateAdvisors(); //查找所有的Advisor中可应用的某个bean的Advisor List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; }
findCandidateAdvisors()源码简单可总结为:从容器中获取所有实现了Advisor的类,在加上aspectJ创建的Advisor。
记下来我们看下findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName)源码
protected List<Advisor> findAdvisorsThatCanApply( List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) { //在ThreadLocal中标记当前beanName ProxyCreationContext.setCurrentProxiedBeanName(beanName); try { return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass); } finally { //在ThreadLocal中移除当前beanName ProxyCreationContext.setCurrentProxiedBeanName(null); } }
AopUtils findAdvisorsThatCanApply源码分析
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) { if (candidateAdvisors.isEmpty()) { return candidateAdvisors; } List<Advisor> eligibleAdvisors = new ArrayList<>(); for (Advisor candidate : candidateAdvisors) { //是否为引入切面并且是否能被应用到 if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) { eligibleAdvisors.add(candidate); } } //目前用不到,所以值为false 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; }
以BeanFactoryTransactionAttributeSourceAdvisor(事务注解关联的Advisor)为例,分析下面源码。BeanFactoryTransactionAttributeSourceAdvisor的切点为TransactionAttributeSourcePointcut,TransactionAttributeSourcePointcut 继承了StaticMethodMatcherPointcut,StaticMethodMatcherPointcut对应的ClassFilter为TrueClassFilter,所以1处会匹配任意类。
StaticMethodMatcherPointcut继承StaticMethodMatcher,所以TransactionAttributeSourcePointcut的MethodMatcher 为TransactionAttributeSourcePointcut自身。所以2处执行的就是TransactionAttributeSourcePointcut的matches(Method method, Class<?> targetClass)方法
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) { Assert.notNull(pc, "Pointcut must not be null"); //1 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<>(); if (!Proxy.isProxyClass(targetClass)) { classes.add(ClassUtils.getUserClass(targetClass)); } classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass)); for (Class<?> clazz : classes) { //获取方法列表包含从父类继承的的方法 Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz); for (Method method : methods) { //2 if (introductionAwareMethodMatcher != null ? introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) : methodMatcher.matches(method, targetClass)) { return true; } } } return false; }
TransactionAttributeSourcePointcut的matches(Method method, Class<?> targetClass)源码:
@Override public boolean matches(Method method, Class<?> targetClass) { if (TransactionalProxy.class.isAssignableFrom(targetClass) || PlatformTransactionManager.class.isAssignableFrom(targetClass) || PersistenceExceptionTranslator.class.isAssignableFrom(targetClass)) { return false; } TransactionAttributeSource tas = getTransactionAttributeSource(); return (tas == null || tas.getTransactionAttribute(method, targetClass) != null); }
先判断TransactionalProxy、PlatformTransactionManager、PersistenceExceptionTranslator是否为当前class的父类,是的话返回false。我们发现TransactionAttributeSourcePointcut其实是个抽象类,而TransactionAttributeSourcePointcut中的getTransactionAttributeSource也是一个抽象方法。从BeanFactoryTransactionAttributeSourceAdvisor源码,我们可以看到,BeanFactoryTransactionAttributeSourceAdvisor定义TransactionAttributeSourcePointcut时,已经重写了该方法
private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() { @Override @Nullable protected TransactionAttributeSource getTransactionAttributeSource() { return transactionAttributeSource; } };
返回的TransactionAttributeSource是BeanFactoryTransactionAttributeSourceAdvisor的一个成员变量。而BeanFactoryTransactionAttributeSourceAdvisor是spring通过@bean配置的(ProxyTransactionManagementConfiguration的transactionAdvisor()方法)
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME) @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() { BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor(); advisor.setTransactionAttributeSource(transactionAttributeSource()); advisor.setAdvice(transactionInterceptor()); if (this.enableTx != null) { advisor.setOrder(this.enableTx.<Integer>getNumber("order")); } return advisor; } @Bean @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public TransactionAttributeSource transactionAttributeSource() { return new AnnotationTransactionAttributeSource(); }
所以最终的TransactionAttributeSource为AnnotationTransactionAttributeSource。AnnotationTransactionAttributeSource调用getTransactionAttribute(method, targetClass)实际上是调用父类AbstractFallbackTransactionAttributeSource中的方法
public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) { if (method.getDeclaringClass() == Object.class) { return null; } // First, see if we have a cached value. Object cacheKey = getCacheKey(method, targetClass); TransactionAttribute cached = this.attributeCache.get(cacheKey); if (cached != null) { // Value will either be canonical value indicating there is no transaction attribute, // or an actual transaction attribute. if (cached == NULL_TRANSACTION_ATTRIBUTE) { return null; } else { return cached; } } else { // We need to work it out. TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass); // Put it in the cache. if (txAttr == null) { this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE); } else { String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass); if (txAttr instanceof DefaultTransactionAttribute) { ((DefaultTransactionAttribute) txAttr).setDescriptor(methodIdentification); } if (logger.isTraceEnabled()) { logger.trace("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr); } this.attributeCache.put(cacheKey, txAttr); } return txAttr; } }
computeTransactionAttribute(method, targetClass)继续向下就会调用AnnotationTransactionAttributeSource中findTransactionAttribute(Method method)、findTransactionAttribute(Class<?> clazz),查找方法或类上是否有Transactional注解。