spring AOP
面向对象编程(OOP),有个局限,当需要为多个不具有继承关系的对象引入一个公共的行为时,例如log,安全检测等,我们只有在每个对象列引入公共行为,这样程序里就产生了大量的公共代码。所以,面向切面编程(AOP)技术就运用而生。AOP关注的是横向的,不同于oop的纵向。
- @AspectJ 注解对pojo进行注解。从而定义一个包含切点的信息和增强横切逻辑的切面。
- @AspectJ 使用AspectJ切点语法表达式语法进行切点定义,可以通过切点函数,运算符,通配符等高级功能进行切点定义,拥有前端打的链接点描述能力。
实例(略)
动态AOP 自定义标签
1 | <!--@AspectJ--> |
2 | <aop:aspectj-autoproxy/> |
spring 中使用了自定义注解,那么在程序的某个地方,一定注册了对应的解析器. 我们尝试搜索整个代码.发现 AopNamespaceHandler
中对应着这样一段代码:
1 | public class AopNamespaceHandler extends NamespaceHandlerSupport { |
2 | |
3 | /** |
4 | * Register the {@link BeanDefinitionParser BeanDefinitionParsers} for the |
5 | * '{@code config}', '{@code spring-configured}', '{@code aspectj-autoproxy}' |
6 | * and '{@code scoped-proxy}' tags. |
7 | */ |
8 | |
9 | public void init() { |
10 | // In 2.0 XSD as well as in 2.1 XSD. |
11 | registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser()); |
12 | //关键点: 一旦遇到 aspectj-autoproxy 注解时,就会使用AspectJAutoProxyBeanDefinitionParser解析 |
13 | registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser()); |
14 | registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator()); |
15 | |
16 | // Only in 2.0 XSD: moved to context namespace as of 2.1 |
17 | registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser()); |
18 | } |
19 | } |
注册 AnnotationAwareAspectJAutoProxyCreator
所有的解析器,因为对 beanDefinitionParser 接口统一实现,入口都是从Parser 函数开始的,AspectJAutoProxyBeanDefinitionParser 的paser函数如下:
1 | class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser { |
2 | |
3 | |
4 | public BeanDefinition parse(Element element, ParserContext parserContext) { |
5 | //注册 AnnotationAwareAspectJAutoProxyCreator |
6 | AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element); |
7 | //拓展功能 |
8 | extendBeanDefinition(element, parserContext); |
9 | return null; |
10 | } |
11 | } |
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary函数是关键逻辑
1 | //AopNamespaceUtils |
2 | public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary( |
3 | ParserContext parserContext, Element sourceElement) { |
4 | // 注册或者升级 AutoProxyCreator 定义为Org.springframework.aop.config.internalAutoProxyCreator 的beanDefinition |
5 | BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary( |
6 | parserContext.getRegistry(), parserContext.extractSource(sourceElement)); |
7 | //对于 proxy-target-class 以及 expose-proxy属性的处理 |
8 | useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement); |
9 | //注册组件并通知,一不安与监听器进一步处理 |
10 | //其中 beanDefintion 的 className 为 AnnotationAwareAspectJAutoProxyCreator |
11 | registerComponentIfNecessary(beanDefinition, parserContext); |
12 | } |
注册或者 升级 AnnotationAwareAspectJAutoProxyCreator
对于aop 的实现,基本上是基于 AnnotationAwareAspectJAutoProxyCreator 去完成的,他可以根据 @Point 注解定义的切点来自动代理相匹配的bean. 但是为了简便,spring使用自定义配置来帮助我们自动注册AnnotationAwareAspectJAutoProxyCreator,其注册过程如下:
1 | //AopNamespaceUtils |
2 | public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) { |
3 | return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source); |
4 | } |
5 | private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) { |
6 | Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); |
7 | //如果已经存在了自动代理创建器且自动代理创建器与现在的不一致,那么需要根据优先级来判断到底使用哪个 |
8 | if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { |
9 | BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME); |
10 | if (!cls.getName().equals(apcDefinition.getBeanClassName())) { |
11 | int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName()); |
12 | int requiredPriority = findPriorityForClass(cls); |
13 | if (currentPriority < requiredPriority) { |
14 | //改变bean 最重要的是改变bean 对应的className属性 |
15 | apcDefinition.setBeanClassName(cls.getName()); |
16 | } |
17 | } |
18 | //如果已经存在自动代理创建器和将要创建的一致,则无需再次创建 |
19 | return null; |
20 | } |
21 | RootBeanDefinition beanDefinition = new RootBeanDefinition(cls); |
22 | beanDefinition.setSource(source); |
23 | beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE); |
24 | beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); |
25 | registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition); |
26 | return beanDefinition; |
27 | } |
处理proxy-target-class 和expose-proxy 属性
useClassProxyingIfNecessary 实现了 proxy-target-class 和 expose-proxy 的处理
1 | private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, Element sourceElement) { |
2 | if (sourceElement != null) { |
3 | //proxy-class-class 的处理 |
4 | boolean proxyTargetClass = Boolean.valueOf(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE)); |
5 | if (proxyTargetClass) { |
6 | AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); |
7 | } |
8 | //expose-proxy 属性的处理 |
9 | boolean exposeProxy = Boolean.valueOf(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE)); |
10 | if (exposeProxy) { |
11 | AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry); |
12 | } |
13 | } |
14 | } |
- AopConfigUtils.forceAutoProxyCreatorToUseClassProxying
1 | //强制使用也是一个设置属性的过程 |
2 | public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) { |
3 | if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { |
4 | BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME); |
5 | definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE); |
6 | } |
7 | } |
AopConfigUtils.forceAutoProxyCreatorToExposeProxy
1
static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {
2
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
3
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
4
definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
5
}
6
}
proxy-target-class: Spring-AOP 部分,使用JDK动态代理或者 CJLIB来为目标对象创建代理.(建议尽量使用JDK动态代理),如果被代理的目标对象至少实现了一个接口,则会使用JDK动态代理.所有该目标类型实现的接口都将会被代理.
若该目标类没有实现任何接口,则创建一个CJLIB动态代理.如果希望强制使用CJLIB来对目标对象创建代理(代理目标对象的所有方法,而不是实现自接口的方法),也可以.需要考虑如下两个问题:
- 无法通知(advise) final 方法,因为他们不能被覆盖
- 我们需要引入CGLIB字节码包
JDK 本身提供了动态代理,强制使用 CGLIB 动态代理,需要将
<aop:config>
的proxy-target-class 属性设置为true1
<aop:config proxy-target-class="true">...</aop:config>
需要CGLIB 代理和@AspectJ 自动代理支持,可以按照以下方式设置aop:aspectj-autoproxy 的proxy-target-class 属性
<aop:aspectj-autoproxy proxy-target-class = "true">
JDK动态代理:其代理对象必须是某个接口的实现,它是通过在运行期间创建一个接口的实现类来完成对目标对象的代理
CGLIB 代理:在运行期间生成的代理对象是目标类扩展的子类.CJLB 是高效的代码生成包.底层是靠ASM(开源的java字节码编辑类库)操作字节码实现的,性能比jdk强.
expose-proxy: 有时候目标对象内部的自我调用无妨实施切面中增强,如下:
1
public interface AService{
2
public void a();
3
4
public void b();
5
}
6
7
8
public class AServiceImpl implements AService{
9
10
(propagation=Propagation.REQUIRED)
11
public void a(){
12
this.b();
13
}
14
(propagation=Propagation.REQUIRES_NEW)
15
public void b(){
16
17
}
18
}
此处的 this指向目标对象,因此调用this.b() 将不会执行b 事务(不会执行事务增强).因此b方法的事务定义
@Transactional(propagation=Propagation.REQUIRES_NEW)
将不会生效.为了解决这个问题,我们可以配置:<aop:aspectj-autoproxy expose-proxy="true">
,然后修改以上代码为:1
(propagation=Propagation.REQUIRED)
2
public void a(){
3
//this.b();
4
(AService)AopContext.currentProxy().b();
5
}
可以完成 b() 方法的增强.
创建 AOP 代理
AnnotationAwareAspectJAutoProxyCreator 类型的自动注册,那么这个类到底做了什么工作来完成 AOP 的操作呢? 首先我们看看 AnnotationAwareAspectJAutoProxyCreator类的层次结构:
我们从 类结构图中,AnnationAwareAspectJAutoProxyCreator 我实现了BeanPostProcessor接口,当Spring 加载这个Bean时,会在实例化前后调用其 postProcessorAfterInitization方法,而我们对于AOP 逻辑的分析也由此开始.
在父类 AbstractAutoProxyCreator 的postProcessAfterInitialization中代码如下:
1 | //AbstractAutoProxyCreator |
2 | |
3 | public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { |
4 | if (bean != null) { |
5 | //依据给定的bean 的class 和 name构建出一个key,格式: beanClassName_beanName |
6 | Object cacheKey = getCacheKey(bean.getClass(), beanName); |
7 | if (!this.earlyProxyReferences.contains(cacheKey)) { |
8 | //如果他适合做代理,则需要封装指定的bean |
9 | return wrapIfNecessary(bean, beanName, cacheKey); |
10 | } |
11 | } |
12 | return bean; |
13 | } |
14 | |
15 | protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { |
16 | //如果已经处理过 |
17 | if (beanName != null && this.targetSourcedBeans.contains(beanName)) { |
18 | return bean; |
19 | } |
20 | //无需增强 |
21 | if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { |
22 | return bean; |
23 | } |
24 | //给定的bean 类是否代表一个基础设施类,基础设施类不应该代理,或者配置了指定bean 不需要被代理 |
25 | if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { |
26 | this.advisedBeans.put(cacheKey, Boolean.FALSE); |
27 | return bean; |
28 | } |
29 | //如果存在增强方法则创建代理 |
30 | // Create proxy if we have advice. |
31 | Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); |
32 | //如果获取到了增强,则需要针对增强创建代理 |
33 | //DO_NOT_PROXY 其实为 null |
34 | if (specificInterceptors != DO_NOT_PROXY) { |
35 | this.advisedBeans.put(cacheKey, Boolean.TRUE); |
36 | Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); |
37 | this.proxyTypes.put(cacheKey, proxy.getClass()); |
38 | return proxy; |
39 | } |
40 | |
41 | this.advisedBeans.put(cacheKey, Boolean.FALSE); |
42 | return bean; |
43 | } |
以上为代理创建的雏形,当然真正创建还需要一些分析和判断.比如是否已经处理过或者需要跳过的bean,而真正创建代码是从 getAdvicesAndAdvisorsForBean
开始的.
创建的步骤为:
- 获取增强方法或者增强器.
- 依据获取到的增强进行代理.
postProcessorAfterInitialization 方法执行示意图:
- getAdvicesAndAdvisorsForBean 方法以上代码功能: 获取所有增强,寻找所有增强中适用于bean 的增强应用
1
//AbstractAdvisorAutoProxyCreator
2
3
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
4
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
5
if (advisors.isEmpty()) {
6
return DO_NOT_PROXY;
7
}
8
return advisors.toArray();
9
}
10
//增强器的解析处理入口
11
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
12
//获取所有的增强(没有初始化的需要解析初始化初始化)
13
List<Advisor> candidateAdvisors = findCandidateAdvisors();
14
//寻找所有增强中适用于bean 的增强应用.
15
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
16
extendAdvisors(eligibleAdvisors);
17
if (!eligibleAdvisors.isEmpty()) {
18
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
19
}
20
return eligibleAdvisors;
21
}
获取增强器
- 获取所有增强器:findCandidateAdvisors
1
//AnnotationAwareAspectJAutoProxyCreator
2
3
protected List<Advisor> findCandidateAdvisors() {
4
//当使用注解方式配置AOP 的时候,并不是抛弃了所有的xml 配置的支持
5
//super.findCandidateAdvisors() 调用父类加载配置文件中的AOP申明
6
// Add all the Spring advisors found according to superclass rules.
7
List<Advisor> advisors = super.findCandidateAdvisors();
8
// Build Advisors for all AspectJ aspects in the bean factory.
9
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
10
return advisors;
11
}
AnnotationAwareAspectJAutoProxyCreator 间接继承了 AbstractAdvisorAutoProxyCreator, 在实现获取增强的方法中,除了父类获取配置文件中的增强外,同时增加了获取Bean 的注解增强功能,其实现是由
this.aspectJAdvisorsBuilder.buildAspectJAdvisors()
来实现的 .
思路:
- 获取所有的beanName,这一步骤,所有在SpringBeanFactory 中注册的bean都会被提取出来.
- 遍历所有的beanName,并找出@AspectJ注解的类, 进行进一步处理.
- 对标记 @AspectJ 注解的类,进行增强器的处理.
- 将提取结果加入缓存.
1 | //BeanFactoryAspectJAdvisorsBuilder |
2 | public List<Advisor> buildAspectJAdvisors() { |
3 | List<String> aspectNames = null; |
4 | |
5 | synchronized (this) { |
6 | aspectNames = this.aspectBeanNames; |
7 | if (aspectNames == null) { |
8 | List<Advisor> advisors = new LinkedList<Advisor>(); |
9 | aspectNames = new LinkedList<String>(); |
10 | //获取所有的bean 名称 |
11 | String[] beanNames = |
12 | BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false); |
13 | //循环所有的bean 名称,找出增强方法 |
14 | for (String beanName : beanNames) { |
15 | //不合法的bean 则略过,默认为true ,由子类定义规则 |
16 | if (!isEligibleBean(beanName)) { |
17 | continue; |
18 | } |
19 | //获取bean 的类型 |
20 | // We must be careful not to instantiate beans eagerly as in this |
21 | // case they would be cached by the Spring container but would not |
22 | // have been weaved |
23 | Class<?> beanType = this.beanFactory.getType(beanName); |
24 | if (beanType == null) { |
25 | continue; |
26 | } |
27 | //如果存在Aspectj注解 |
28 | if (this.advisorFactory.isAspect(beanType)) { |
29 | aspectNames.add(beanName); |
30 | AspectMetadata amd = new AspectMetadata(beanType, beanName); |
31 | if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) { |
32 | MetadataAwareAspectInstanceFactory factory = |
33 | new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName); |
34 | //解析Aspectj注解中增强的方法 |
35 | List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory); |
36 | if (this.beanFactory.isSingleton(beanName)) { |
37 | this.advisorsCache.put(beanName, classAdvisors); |
38 | } |
39 | else { |
40 | this.aspectFactoryCache.put(beanName, factory); |
41 | } |
42 | advisors.addAll(classAdvisors); |
43 | } |
44 | else { |
45 | // Per target or per this. |
46 | if (this.beanFactory.isSingleton(beanName)) { |
47 | throw new IllegalArgumentException("Bean with name '" + beanName + |
48 | "' is a singleton, but aspect instantiation model is not singleton"); |
49 | } |
50 | MetadataAwareAspectInstanceFactory factory = |
51 | new PrototypeAspectInstanceFactory(this.beanFactory, beanName); |
52 | this.aspectFactoryCache.put(beanName, factory); |
53 | advisors.addAll(this.advisorFactory.getAdvisors(factory)); |
54 | } |
55 | } |
56 | } |
57 | this.aspectBeanNames = aspectNames; |
58 | return advisors; |
59 | } |
60 | } |
61 | |
62 | if (aspectNames.isEmpty()) { |
63 | return Collections.emptyList(); |
64 | } |
65 | //记录在缓存中 |
66 | List<Advisor> advisors = new LinkedList<Advisor>(); |
67 | for (String aspectName : aspectNames) { |
68 | List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName); |
69 | if (cachedAdvisors != null) { |
70 | advisors.addAll(cachedAdvisors); |
71 | } |
72 | else { |
73 | MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName); |
74 | advisors.addAll(this.advisorFactory.getAdvisors(factory)); |
75 | } |
76 | } |
77 | return advisors; |
78 | } |
增强器的获取 advisorFactory.getAdvisors()
1 | //ReflectiveAspectJAdvisorFactory |
2 |
|
3 | public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory maaif) { |
4 | //获取标记为 Aspectj 的类 |
5 | final Class<?> aspectClass = maaif.getAspectMetadata().getAspectClass(); |
6 | // 获取标记为Aspectj 类的名称 |
7 | final String aspectName = maaif.getAspectMetadata().getAspectName(); |
8 | //验证 |
9 | validate(aspectClass); |
10 | |
11 | // We need to wrap the MetadataAwareAspectInstanceFactory with a decorator |
12 | // so that it will only instantiate once. |
13 | final MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory = |
14 | new LazySingletonAspectInstanceFactoryDecorator(maaif); |
15 | |
16 | final List<Advisor> advisors = new LinkedList<Advisor>(); |
17 | for (Method method : getAdvisorMethods(aspectClass)) { |
18 | Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName); |
19 | if (advisor != null) { |
20 | advisors.add(advisor); |
21 | } |
22 | } |
23 | //如果增强器不为空,而且配置了延迟增强初始化,那么需要在首位加入同步实例化增强器 |
24 | // If it's a per target aspect, emit the dummy instantiating aspect. |
25 | if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) { |
26 | Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory); |
27 | advisors.add(0, instantiationAdvisor); |
28 | } |
29 | //获取 DeclareParents 注解 |
30 | // Find introduction fields. |
31 | for (Field field : aspectClass.getDeclaredFields()) { |
32 | Advisor advisor = getDeclareParentsAdvisor(field); |
33 | if (advisor != null) { |
34 | advisors.add(advisor); |
35 | } |
36 | } |
37 | |
38 | return advisors; |
39 | } |
40 | |
41 | private List<Method> getAdvisorMethods(Class<?> aspectClass) { |
42 | final List<Method> methods = new LinkedList<Method>(); |
43 | ReflectionUtils.doWithMethods(aspectClass, new ReflectionUtils.MethodCallback() { |
44 | |
45 | public void doWith(Method method) throws IllegalArgumentException { |
46 | //申明为pointcout 的方法不处理 |
47 | // Exclude pointcuts |
48 | if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) { |
49 | methods.add(method); |
50 | } |
51 | } |
52 | }); |
53 | Collections.sort(methods, METHOD_COMPARATOR); |
54 | return methods; |
55 | } |
以上方法中完成了对增强器的获取:
- 包括注解以及根据注解生成增强器的步骤,
- 然后考虑到在配置中可能会将增强器配置成延时初始化,那么需要在首位加入同步实例化增强器以保证增强器使用之前被实例化,
- 最后是对DeclareParents 注解的获取
普通增强器 的获取
包括对注解切点的获取 和依据注解信息进行增强
1 | //ReflectiveAspectJAdvisorFactory |
2 | public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aif, |
3 | int declarationOrderInAspect, String aspectName) { |
4 | |
5 | validate(aif.getAspectMetadata().getAspectClass()); |
6 | //切点信息的获取 |
7 | AspectJExpressionPointcut ajexp = |
8 | getPointcut(candidateAdviceMethod, aif.getAspectMetadata().getAspectClass()); |
9 | if (ajexp == null) { |
10 | return null; |
11 | } |
12 | //依据切点信息生成增强器 |
13 | return new InstantiationModelAwarePointcutAdvisorImpl( |
14 | this, ajexp, aif, candidateAdviceMethod, declarationOrderInAspect, aspectName); |
15 | } |
- 切点信息获取
1
////ReflectiveAspectJAdvisorFactory
2
//切点信息获取
3
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
4
//获取方法上的注解
5
AspectJAnnotation<?> aspectJAnnotation =
6
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
7
if (aspectJAnnotation == null) {
8
return null;
9
}
10
// 使用 AspectJExpressionPointcut 封装获取到的切点信息
11
AspectJExpressionPointcut ajexp =
12
new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
13
//提取注解中的表达式:@pointcout("execution(* *.*test*(..))") 中的 execution(* *.*test*(..))
14
ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
15
return ajexp;
16
}
17
18
//AbstractAspectJAdvisorFactory
19
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
20
Class<?>[] classesToLookFor = new Class<?>[] {
21
Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class};
22
for (Class<?> c : classesToLookFor) {
23
AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) c);
24
if (foundAnnotation != null) {
25
return foundAnnotation;
26
}
27
}
28
return null;
29
}
30
// 获取指定方法上注解并使用的AspectJAnnotation封装
31
private static <A extends Annotation> AspectJAnnotation<A> findAnnotation(Method method, Class<A> toLookFor) {
32
A result = AnnotationUtils.findAnnotation(method, toLookFor);
33
if (result != null) {
34
return new AspectJAnnotation<A>(result);
35
}
36
else {
37
return null;
38
}
39
}
- 依据切点信息生成增强
所有的增强都由Advisor 的实现类InstantiationModelAwarePointcutAdvisorImpl
统一封装在封装过程中还是简单的将信息封装到实例中,所有的信息单纯的赋值,在实例初始化的过程中还完成了增强器的初始化,因为不同的增强所体现的逻辑是不同的,如:1
//InstantiationModelAwarePointcutAdvisorImpl
2
public InstantiationModelAwarePointcutAdvisorImpl(AspectJAdvisorFactory af, AspectJExpressionPointcut ajexp,
3
MetadataAwareAspectInstanceFactory aif, Method method, int declarationOrderInAspect, String aspectName) {
4
5
this.declaredPointcut = ajexp;
6
this.method = method;
7
this.atAspectJAdvisorFactory = af;
8
this.aspectInstanceFactory = aif;
9
this.declarationOrder = declarationOrderInAspect;
10
this.aspectName = aspectName;
11
12
if (aif.getAspectMetadata().isLazilyInstantiated()) {
13
// Static part of the pointcut is a lazy type.
14
Pointcut preInstantiationPointcut =
15
Pointcuts.union(aif.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
16
17
// Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
18
// If it's not a dynamic pointcut, it may be optimized out
19
// by the Spring AOP infrastructure after the first evaluation.
20
this.pointcut = new PerTargetInstantiationModelPointcut(this.declaredPointcut, preInstantiationPointcut, aif);
21
this.lazy = true;
22
}
23
else {
24
//增强器的初始化
25
// A singleton aspect.
26
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
27
this.pointcut = declaredPointcut;
28
this.lazy = false;
29
}
30
}
@before("test()")
和@after("test()")
标签的不同就是增强位置不同. 所以需要不同的增强其来完成不同的逻辑,依据注解中的信息初始化对应的对应的增强器的逻辑就是在instantiateAdvice
中完成.1
//InstantiationModelAwarePointcutAdvisorImpl
2
private Advice instantiateAdvice(AspectJExpressionPointcut pcut) {
3
return this.atAspectJAdvisorFactory.getAdvice(
4
this.method, pcut, this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
5
}
6
7
//ReflectiveAspectJAdvisorFactory
8
9
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut ajexp,
10
MetadataAwareAspectInstanceFactory aif, int declarationOrderInAspect, String aspectName) {
11
12
Class<?> candidateAspectClass = aif.getAspectMetadata().getAspectClass();
13
validate(candidateAspectClass);
14
15
AspectJAnnotation<?> aspectJAnnotation =
16
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
17
if (aspectJAnnotation == null) {
18
return null;
19
}
20
// 判断 该类上是否有 @AspectJ 注解
21
// If we get here, we know we have an AspectJ method.
22
// Check that it's an AspectJ-annotated class
23
if (!isAspect(candidateAspectClass)) {
24
throw new AopConfigException("Advice must be declared inside an aspect type: " +
25
"Offending method '" + candidateAdviceMethod + "' in class [" +
26
candidateAspectClass.getName() + "]");
27
}
28
29
AbstractAspectJAdvice springAdvice;
30
//依据不同的注解类型封装不同的增强器
31
switch (aspectJAnnotation.getAnnotationType()) {
32
case AtBefore:
33
springAdvice = new AspectJMethodBeforeAdvice(candidateAdviceMethod, ajexp, aif);
34
break;
35
case AtAfter:
36
springAdvice = new AspectJAfterAdvice(candidateAdviceMethod, ajexp, aif);
37
break;
38
case AtAfterReturning:
39
springAdvice = new AspectJAfterReturningAdvice(candidateAdviceMethod, ajexp, aif);
40
AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
41
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
42
springAdvice.setReturningName(afterReturningAnnotation.returning());
43
}
44
break;
45
case AtAfterThrowing:
46
springAdvice = new AspectJAfterThrowingAdvice(candidateAdviceMethod, ajexp, aif);
47
AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
48
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
49
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
50
}
51
break;
52
case AtAround:
53
springAdvice = new AspectJAroundAdvice(candidateAdviceMethod, ajexp, aif);
54
break;
55
case AtPointcut:
56
if (logger.isDebugEnabled()) {
57
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
58
}
59
return null;
60
default:
61
throw new UnsupportedOperationException(
62
"Unsupported advice type on method " + candidateAdviceMethod);
63
}
64
65
// Now to configure the advice...
66
springAdvice.setAspectName(aspectName);
67
springAdvice.setDeclarationOrder(declarationOrderInAspect);
68
String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
69
if (argNames != null) {
70
springAdvice.setArgumentNamesFromStringArray(argNames);
71
}
72
springAdvice.calculateArgumentBindings();
73
return springAdvice;
74
}
分析几个常用增强器的实现
- MethodBeforeAdviceInterceptor
1 | public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable { |
2 | |
3 | private MethodBeforeAdvice advice; |
4 | |
5 | |
6 | /** |
7 | * Create a new MethodBeforeAdviceInterceptor for the given advice. |
8 | * @param advice the MethodBeforeAdvice to wrap |
9 | */ |
10 | public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) { |
11 | Assert.notNull(advice, "Advice must not be null"); |
12 | this.advice = advice; |
13 | } |
14 | |
15 | public Object invoke(MethodInvocation mi) throws Throwable { |
16 | this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() ); |
17 | return mi.proceed(); |
18 | } |
19 | } |
MethodBeforeAdvice 代表 AspectJMethodBeforeAdvice,查看before方法
1 | //AspectJMethodBeforeAdvice |
2 | public void before(Method method, Object[] args, Object target) throws Throwable { |
3 | invokeAdviceMethod(getJoinPointMatch(), null, null); |
4 | } |
5 | |
6 | //AbstractAspectJAdvice |
7 | protected Object invokeAdviceMethod(JoinPointMatch jpMatch, Object returnValue, Throwable ex) throws Throwable { |
8 | return invokeAdviceMethodWithGivenArgs(argBinding(getJoinPoint(), jpMatch, returnValue, ex)); |
9 | } |
10 | protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable { |
11 | Object[] actualArgs = args; |
12 | if (this.aspectJAdviceMethod.getParameterTypes().length == 0) { |
13 | actualArgs = null; |
14 | } |
15 | try { |
16 | ReflectionUtils.makeAccessible(this.aspectJAdviceMethod); |
17 | // TODO AopUtils.invokeJoinpointUsingReflection |
18 | //激活增强方法 |
19 | return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs); |
20 | } |
21 | catch (IllegalArgumentException ex) { |
22 | throw new AopInvocationException("Mismatch on arguments to advice method [" + |
23 | this.aspectJAdviceMethod + "]; pointcut expression [" + |
24 | this.pointcut.getPointcutExpression() + "]", ex); |
25 | } |
26 | catch (InvocationTargetException ex) { |
27 | throw ex.getTargetException(); |
28 | } |
29 | } |
invokeAdviceMethodWithGivenArgs 中的 aspectJAdviceMethod
正是对于前置增强的方法,在这里实现了调用。
大致的逻辑是在拦截器中放置MethodBeforeAdviceInterceptor,而在 MethodBeforeAdviceInterceptor中又放置了AspectJMethodBeforeAdvice,并在调用invoke 时首先串联调用。
- AspectJAfterAdvice
后置增强与前置增强稍有不同的地方。后置增强器没有提供中间类,而是直接在拦截器链中使用了中间的AspectJAfterAdvice
。1
public class AspectJAfterAdvice extends AbstractAspectJAdvice implements MethodInterceptor, AfterAdvice {
2
public AspectJAfterAdvice(
3
Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
4
5
super(aspectJBeforeAdviceMethod, pointcut, aif);
6
}
7
8
public Object invoke(MethodInvocation mi) throws Throwable {
9
try {
10
return mi.proceed();
11
}
12
finally {
13
// 激活增强方法
14
invokeAdviceMethod(getJoinPointMatch(), null, null);
15
}
16
}
17
18
public boolean isBeforeAdvice() {
19
return false;
20
}
21
22
public boolean isAfterAdvice() {
23
return true;
24
}
25
26
}
增加同步实例化增强器
如果寻找的增强器部位空,且又配置了增强延迟初始化,那么就需要在首位加入同步实例化增强器。同步实例化增强器SyntheticInstantiationAdvisor
如下:
1 | protected static class SyntheticInstantiationAdvisor extends DefaultPointcutAdvisor { |
2 | |
3 | public SyntheticInstantiationAdvisor(final MetadataAwareAspectInstanceFactory aif) { |
4 | super(aif.getAspectMetadata().getPerClausePointcut(), new MethodBeforeAdvice() { |
5 | // 目标方法调用前调用,类似与 @Before |
6 | |
7 | public void before(Method method, Object[] args, Object target) { |
8 | // 简单初始化 aspectj |
9 | // Simply instantiate the aspect |
10 | aif.getAspectInstance(); |
11 | } |
12 | }); |
13 | } |
14 | } |
获取 DeclareParent 注解
主要用于引进增强注解形式的实现,实现与普通的实现很类似,只不过是使用DeclareParentsAdvisor对功能进行封装
1 | private Advisor getDeclareParentsAdvisor(Field introductionField) { |
2 | DeclareParents declareParents = introductionField.getAnnotation(DeclareParents.class); |
3 | if (declareParents == null) { |
4 | // Not an introduction field |
5 | return null; |
6 | } |
7 | |
8 | if (DeclareParents.class.equals(declareParents.defaultImpl())) { |
9 | // This is what comes back if it wasn't set. This seems bizarre... |
10 | // TODO this restriction possibly should be relaxed |
11 | throw new IllegalStateException("defaultImpl must be set on DeclareParents"); |
12 | } |
13 | |
14 | return new DeclareParentsAdvisor( |
15 | introductionField.getType(), declareParents.value(), declareParents.defaultImpl()); |
16 | } |
寻找匹配的增强器
前面完成了 所有增强器的解析,但是对于增强器来说,一定要适用于当前的bean,还要挑出适合的增强器,即满足通配符的增强器,具体实现在 findAdvisorsThatCanApply 中
1 | //AbstractAdvisorAutoProxyCreator |
2 | protected List<Advisor> findAdvisorsThatCanApply( |
3 | List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) { |
4 | |
5 | ProxyCreationContext.setCurrentProxiedBeanName(beanName); |
6 | try { |
7 | // 过滤已经得到的增强器 |
8 | return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass); |
9 | } |
10 | finally { |
11 | ProxyCreationContext.setCurrentProxiedBeanName(null); |
12 | } |
13 | } |
- AopUtils.findAdvisorsThatCanApply主要功能是找出所有增强器中适合当前class的增强器,引介增强和普通的增强不一样的,所以分开处理.而真正的处理在 canApply 中
1
//AopUtils
2
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
3
if (candidateAdvisors.isEmpty()) {
4
return candidateAdvisors;
5
}
6
List<Advisor> eligibleAdvisors = new LinkedList<Advisor>();
7
//首先处理引介增强
8
for (Advisor candidate : candidateAdvisors) {
9
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
10
eligibleAdvisors.add(candidate);
11
}
12
}
13
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
14
for (Advisor candidate : candidateAdvisors) {
15
//引介增强已经处理
16
if (candidate instanceof IntroductionAdvisor) {
17
// already processed
18
continue;
19
}
20
//对普通bean 的处理
21
if (canApply(candidate, clazz, hasIntroductions)) {
22
eligibleAdvisors.add(candidate);
23
}
24
}
25
return eligibleAdvisors;
26
}
1
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
2
if (advisor instanceof IntroductionAdvisor) {
3
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
4
}
5
else if (advisor instanceof PointcutAdvisor) {
6
PointcutAdvisor pca = (PointcutAdvisor) advisor;
7
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
8
}
9
else {
10
// It doesn't have a pointcut so we assume it applies.
11
return true;
12
}
13
}
14
15
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
16
Assert.notNull(pc, "Pointcut must not be null");
17
if (!pc.getClassFilter().matches(targetClass)) {
18
return false;
19
}
20
21
MethodMatcher methodMatcher = pc.getMethodMatcher();
22
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
23
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
24
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
25
}
26
27
Set<Class<?>> classes = new LinkedHashSet<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
28
classes.add(targetClass);
29
for (Class<?> clazz : classes) {
30
Method[] methods = clazz.getMethods();
31
for (Method method : methods) {
32
if ((introductionAwareMethodMatcher != null &&
33
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
34
methodMatcher.matches(method, targetClass)) {
35
return true;
36
}
37
}
38
}
39
40
return false;
41
}
创建代理
获取所有bean 的增强器后,可以创建代理了
1 | //AbstractAutoProxyCreator |
2 | protected Object createProxy( |
3 | Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) { |
4 | |
5 | ProxyFactory proxyFactory = new ProxyFactory(); |
6 | //获取当前类中的相关属性 |
7 | proxyFactory.copyFrom(this); |
8 | //决定于给定的bean 是否应该使用targetClass而不是他的接口代理 |
9 | //检查proxyTargetClass设置以及preserveTargetClass属性 |
10 | if (!proxyFactory.isProxyTargetClass()) { |
11 | //判断代理类是否代理目标类 |
12 | if (shouldProxyTargetClass(beanClass, beanName)) { |
13 | proxyFactory.setProxyTargetClass(true); |
14 | } |
15 | else { |
16 | //代理类代理接口时 |
17 | evaluateProxyInterfaces(beanClass, proxyFactory); |
18 | } |
19 | } |
20 | |
21 | Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); |
22 | for (Advisor advisor : advisors) { |
23 | //添加增强器 |
24 | proxyFactory.addAdvisor(advisor); |
25 | } |
26 | //设置要代理的类 |
27 | proxyFactory.setTargetSource(targetSource); |
28 | //定制代理 |
29 | customizeProxyFactory(proxyFactory); |
30 | //控制代理工厂被配置后,是否允许修改通知 |
31 | //缺省值为false, 即代理被配置后,不允许修改代理的配置 |
32 | proxyFactory.setFrozen(this.freezeProxy); |
33 | if (advisorsPreFiltered()) { |
34 | proxyFactory.setPreFiltered(true); |
35 | } |
36 | // 对于代理的创建和处理,都交给 proxyFactory.getProxy 去处理. |
37 | return proxyFactory.getProxy(getProxyClassLoader()); |
38 | } |
代理类的创建即处理,spring 都交给了 ProxyFactory.以上代码的主要功能是:
- 获取当前类中的属性
- 添加代理接口
- 封装 Advisor 并加入到ProxyFactory 中
- 设置要代理的类
- spring 为子类提供了定制函数
customizeProxyFactory
, 子类可以在 该函数中对 ProxyFactory 进行进一步封装- 获取代理操作
封装 Advisor 并加入到ProxyFactory是一个比较繁琐的过程,可以通过 ProxyFactory 提供的 addAdvisor方法直接将增强器置入代理创建工厂中,但是将拦截器封装为增强器还要一定的逻辑.
1
//AbstractAutoProxyCreator
2
protected Advisor[] buildAdvisors(String beanName, Object[] specificInterceptors) {
3
// 解析所有注册的拦截器
4
// Handle prototypes correctly...
5
Advisor[] commonInterceptors = resolveInterceptorNames();
6
7
List<Object> allInterceptors = new ArrayList<Object>();
8
if (specificInterceptors != null) {
9
//加入拦截器
10
allInterceptors.addAll(Arrays.asList(specificInterceptors));
11
if (commonInterceptors != null) {
12
if (this.applyCommonInterceptorsFirst) {
13
allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
14
}
15
else {
16
allInterceptors.addAll(Arrays.asList(commonInterceptors));
17
}
18
}
19
}
20
if (logger.isDebugEnabled()) {
21
int nrOfCommonInterceptors = (commonInterceptors != null ? commonInterceptors.length : 0);
22
int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);
23
logger.debug("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
24
" common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
25
}
26
27
Advisor[] advisors = new Advisor[allInterceptors.size()];
28
for (int i = 0; i < allInterceptors.size(); i++) {
29
//将拦截器转化为 advisor
30
advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
31
}
32
return advisors;
33
}
34
35
//DefaultAdvisorAdapterRegistry
36
37
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
38
//如果要封装的对象本身是 Advisor类型的,则无需做过多的处理
39
if (adviceObject instanceof Advisor) {
40
return (Advisor) adviceObject;
41
}
42
//因为此封装方法只支持 Advisor 和 Advisor 两种类型
43
if (!(adviceObject instanceof Advice)) {
44
throw new UnknownAdviceTypeException(adviceObject);
45
}
46
Advice advice = (Advice) adviceObject;
47
// 如果是 MethodInterceptor类型, 则使用 DefaultPointcutAdvisor 封装
48
if (advice instanceof MethodInterceptor) {
49
// So well-known it doesn't even need an adapter.
50
return new DefaultPointcutAdvisor(advice);
51
}
52
//如果存在 Advisor 的适配器,也需要进行封装
53
for (AdvisorAdapter adapter : this.adapters) {
54
// Check that it is supported.
55
if (adapter.supportsAdvice(advice)) {
56
return new DefaultPointcutAdvisor(advice);
57
}
58
}
59
throw new UnknownAdviceTypeException(advice);
60
}
在spring 中使用了大量的拦截器,增强器,增强方法等方式来对逻辑进行增强,所以非常由必要封装成统一的 advisor 来进行代理的创建,完成了增强的过程,解析最终要的一步就是代理的创建于获取.
1 | //ProxyFactory |
2 | public Object getProxy(ClassLoader classLoader) { |
3 | return createAopProxy().getProxy(classLoader); |
4 | } |
创建代理
1 | //ProxyFactory |
2 | protected final synchronized AopProxy createAopProxy() { |
3 | if (!this.active) { |
4 | activate(); |
5 | } |
6 | // 创建代理 |
7 | return getAopProxyFactory().createAopProxy(this); |
8 | } |
9 | //DefaultAopProxyFactory |
10 | public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { |
11 | if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { |
12 | Class<?> targetClass = config.getTargetClass(); |
13 | if (targetClass == null) { |
14 | throw new AopConfigException("TargetSource cannot determine target class: " + |
15 | "Either an interface or a target is required for proxy creation."); |
16 | } |
17 | if (targetClass.isInterface()) { |
18 | return new JdkDynamicAopProxy(config); |
19 | } |
20 | return new ObjenesisCglibAopProxy(config); |
21 | } |
22 | else { |
23 | return new JdkDynamicAopProxy(config); |
24 | } |
25 | } |
上段代码完成了 代理的创建,spring 是如何选择 代理方式的呢?
从以上代码的if 判断中,我们发现三个方面引响这是平日那个的判断:
- optimize 用来控制通过 CJLIB 创建的代理是否使用激进的优化策略,除非完全了解AOP 代理如何处理优化,否则不推荐用户使用这个设置。 目前这个属性仅用于CJLIB 代理,对于 JDK(默认代理) 无效。
- proxyTargetClass: 这个属性为true时,目标类本身被代理而不是接口。如果proxyTargetClass = true,CGLIB 代理将被创建,设置方式为:
<aop:aspectj-autoproxy proxy-target-class= "true"/>
- hasNoUserSuppliedProxyInterfaces: 是否存在接口代理
JDK 和 CGLIB 方式总结
- 如果目标对象实现了接口,默认是采用JDK 动态代理来实现AOP
- 目标对象实现了接口,也可以强制使用 CGLIB 动态代理来实现 AOP
- 如果目标对象没有实现接口,则默认使用CGLIB 动态代理来实现 AOP
- 默认情况下,spring 会在 CGLIB 和 JDK 动态代理之间自动转换
如何强制使用CGLIB 动态代理
- 添加 CGLIB 库。
- 在spring 配置文件中 使用
<aop:aspectj_autoproxy proxy-target-class== "true">
JDK动态代理和 CGLIB动态代理的区别
- jdk 动态代理能对实现接口的类生成代理,而不能对未实现接口的类生成代理
- CGLIB 是针对实现代理,主要是对指定的类生成一个子类,子类覆盖其中的方法。 而目标类类中的方法不能被申明为final的。
获取代理
1 | //ProxyFactory |
2 | public Object getProxy(ClassLoader classLoader) { |
3 | return createAopProxy().getProxy(classLoader); |
4 | } |
getproxy 获取的是 AopProxy 接口,而AopProxy 接口的实现关系如下图
spring 的jdk 动态代理
1 | //JdkDynamicAopProxy |
2 |
|
3 | public Object getProxy(ClassLoader classLoader) { |
4 | if (logger.isDebugEnabled()) { |
5 | logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource()); |
6 | } |
7 | Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised); |
8 | findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); |
9 | return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); |
10 | } |
JDKproxy 的关键是创建自定义的InvocationHandler,而InvocationHandler中包含了虚哟覆盖的 getProxy,而当前的方法正是完成了这个操作,同时,我们发现JdkDynamicAopProxy 也实现了 InvocationHandler 接口,那么,我们推断出,在 getProxy,而当前的方法正是完成了这个操作,同时,我们发现JdkDynamicAopProxy中一定有invoke 方法,getProxy,而当前的方法正是完成了这个操作,同时,我们发现JdkDynamicAopProxy的核心逻辑应该就在其中。
1 | //JdkDynamicAopProxy |
2 |
|
3 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { |
4 | MethodInvocation invocation; |
5 | Object oldProxy = null; |
6 | boolean setProxyContext = false; |
7 | |
8 | TargetSource targetSource = this.advised.targetSource; |
9 | Class<?> targetClass = null; |
10 | Object target = null; |
11 | |
12 | try { |
13 | if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { |
14 | // The target does not implement the equals(Object) method itself. |
15 | return equals(args[0]); |
16 | } |
17 | if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { |
18 | // The target does not implement the hashCode() method itself. |
19 | return hashCode(); |
20 | } |
21 | //Class 类的isAssignableFrom方法: |
22 | //如果调用这个方法的接口或者类与参数 cls表示的类或者接口相同,或者是参数 cls 表示的父类或者接口 这返回true |
23 | //A.class.isAssignableFrom(A.class); 返回true |
24 | // Arraylist.class.isAssignableFrom(Object.class); 返回false |
25 | // Object.class.isAssignableFrom(ArrayList.class); 返回true |
26 | if (!this.advised.opaque && method.getDeclaringClass().isInterface() && |
27 | method.getDeclaringClass().isAssignableFrom(Advised.class)) { |
28 | // Service invocations on ProxyConfig with the proxy config... |
29 | return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); |
30 | } |
31 | |
32 | Object retVal; |
33 | //目标对象内部的自我调用,将无法实施切面中的增强,则需要通过此属性来暴露代理 |
34 | if (this.advised.exposeProxy) { |
35 | // Make invocation available if necessary. |
36 | oldProxy = AopContext.setCurrentProxy(proxy); |
37 | setProxyContext = true; |
38 | } |
39 | |
40 | // May be null. Get as late as possible to minimize the time we "own" the target, |
41 | // in case it comes from a pool. |
42 | target = targetSource.getTarget(); |
43 | if (target != null) { |
44 | targetClass = target.getClass(); |
45 | } |
46 | // 获取当前方法的拦截器链 |
47 | // Get the interception chain for this method. |
48 | List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); |
49 | // 如果没有获取到任何拦截器,那么直接调用切点方法 |
50 | // Check whether we have any advice. If we don't, we can fallback on direct |
51 | // reflective invocation of the target, and avoid creating a MethodInvocation. |
52 | if (chain.isEmpty()) { |
53 | // We can skip creating a MethodInvocation: just invoke the target directly |
54 | // Note that the final invoker must be an InvokerInterceptor so we know it does |
55 | // nothing but a reflective operation on the target, and no hot swapping or fancy proxying. |
56 | retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args); |
57 | } |
58 | else { |
59 | // 将拦截器封装在 ReflectiveMethodInvocation中 |
60 | //以便于使用 其proceed进行链接表用拦截器 |
61 | // We need to create a method invocation... |
62 | invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); |
63 | // Proceed to the joinpoint through the interceptor chain. |
64 | // 执行拦截器链 |
65 | retVal = invocation.proceed(); |
66 | } |
67 | // 返回结果 |
68 | // Massage return value if necessary. |
69 | Class<?> returnType = method.getReturnType(); |
70 | if (retVal != null && retVal == target && returnType.isInstance(proxy) && |
71 | !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { |
72 | // Special case: it returned "this" and the return type of the method |
73 | // is type-compatible. Note that we can't help if the target sets |
74 | // a reference to itself in another returned object. |
75 | retVal = proxy; |
76 | } |
77 | else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) { |
78 | throw new AopInvocationException( |
79 | "Null return value from advice does not match primitive return type for: " + method); |
80 | } |
81 | return retVal; |
82 | } |
83 | finally { |
84 | if (target != null && !targetSource.isStatic()) { |
85 | // Must have come from TargetSource. |
86 | targetSource.releaseTarget(target); |
87 | } |
88 | if (setProxyContext) { |
89 | // Restore old proxy. |
90 | AopContext.setCurrentProxy(oldProxy); |
91 | } |
92 | } |
93 | } |
以上函数的主要工作是创建一个拦截器链,并使用 ReflectiveMethodInvocation
对拦截器链封装,而在 ReflectiveMethodInvocation
类的 proceed 方法中是怎么实现前置增强是在目标方法调用之前,后置增强是在目标方法调用之后呢?
1 | //ReflectiveMethodInvocation |
2 |
|
3 | public Object proceed() throws Throwable { |
4 | //执行完所有增强后执行切点方法 |
5 | // We start with an index of -1 and increment early. |
6 | if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { |
7 | return invokeJoinpoint(); |
8 | } |
9 | // 获取下一个要执行的拦截器 |
10 | Object interceptorOrInterceptionAdvice = |
11 | this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); |
12 | if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { |
13 | // 动态匹配 |
14 | // Evaluate dynamic method matcher here: static part will already have |
15 | // been evaluated and found to match. |
16 | InterceptorAndDynamicMethodMatcher dm = |
17 | (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice; |
18 | if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) { |
19 | return dm.interceptor.invoke(this); |
20 | } |
21 | else { |
22 | // 不匹配则步执行,执行下一个拦截器 |
23 | // Dynamic matching failed. |
24 | // Skip this interceptor and invoke the next in the chain. |
25 | return proceed(); |
26 | } |
27 | } |
28 | else { |
29 | // 普通拦截器,则直接调用拦截器: |
30 | // Exposeinvocationinterceptor |
31 | // DelegatePerTargetObjectIntroductionInteceptor |
32 | // MethodBeforeAdviceInteceptor |
33 | // AspectJAroundAdvice |
34 | // AspectJAfterAdvice |
35 | // It's an interceptor, so we just invoke it: The pointcut will have |
36 | // been evaluated statically before this object was constructed. |
37 | return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); |
38 | } |
39 | } |
proceed 方法逻辑是: 在 ReflectiveMethodInvocation
中链接调用的计数器,记录着当前调用链的位置,以便于可以有序的进行下去,在 proceed 方法中并没有维护各种增强的顺序的逻辑,而是将此工作委托给了各个增强器,使得各个增强器在内部进行逻辑实现。
CGLIB 动态代理
Spring 的 CGLIB 动态代理是委托给 Spring 的CglibAopProxy
1 | //CglibAopProxy |
2 |
|
3 | public Object getProxy() { |
4 | return getProxy(null); |
5 | } |
6 | |
7 | |
8 | public Object getProxy(ClassLoader classLoader) { |
9 | if (logger.isDebugEnabled()) { |
10 | logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource()); |
11 | } |
12 | |
13 | try { |
14 | Class<?> rootClass = this.advised.getTargetClass(); |
15 | Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy"); |
16 | |
17 | Class<?> proxySuperClass = rootClass; |
18 | if (ClassUtils.isCglibProxyClass(rootClass)) { |
19 | proxySuperClass = rootClass.getSuperclass(); |
20 | Class<?>[] additionalInterfaces = rootClass.getInterfaces(); |
21 | for (Class<?> additionalInterface : additionalInterfaces) { |
22 | this.advised.addInterface(additionalInterface); |
23 | } |
24 | } |
25 | |
26 | // Validate the class, writing log messages as necessary. |
27 | validateClassIfNecessary(proxySuperClass, classLoader); |
28 | // 创建Ebhancer |
29 | // Configure CGLIB Enhancer... |
30 | Enhancer enhancer = createEnhancer(); |
31 | if (classLoader != null) { |
32 | enhancer.setClassLoader(classLoader); |
33 | if (classLoader instanceof SmartClassLoader && |
34 | ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) { |
35 | enhancer.setUseCache(false); |
36 | } |
37 | } |
38 | enhancer.setSuperclass(proxySuperClass); |
39 | enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised)); |
40 | enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE); |
41 | enhancer.setStrategy(new UndeclaredThrowableStrategy(UndeclaredThrowableException.class)); |
42 | //设置拦截器 |
43 | Callback[] callbacks = getCallbacks(rootClass); |
44 | Class<?>[] types = new Class<?>[callbacks.length]; |
45 | for (int x = 0; x < types.length; x++) { |
46 | types[x] = callbacks[x].getClass(); |
47 | } |
48 | // fixedInterceptorMap only populated at this point, after getCallbacks call above |
49 | enhancer.setCallbackFilter(new ProxyCallbackFilter( |
50 | this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset)); |
51 | enhancer.setCallbackTypes(types); |
52 | // 生成代理类以及创建代理 |
53 | // Generate the proxy class and create a proxy instance. |
54 | return createProxyClassAndInstance(enhancer, callbacks); |
55 | } |
56 | catch (CodeGenerationException ex) { |
57 | throw new AopConfigException("Could not generate CGLIB subclass of class [" + |
58 | this.advised.getTargetClass() + "]: " + |
59 | "Common causes of this problem include using a final class or a non-visible class", |
60 | ex); |
61 | } |
62 | catch (IllegalArgumentException ex) { |
63 | throw new AopConfigException("Could not generate CGLIB subclass of class [" + |
64 | this.advised.getTargetClass() + "]: " + |
65 | "Common causes of this problem include using a final class or a non-visible class", |
66 | ex); |
67 | } |
68 | catch (Exception ex) { |
69 | // TargetSource.getTarget() failed |
70 | throw new AopConfigException("Unexpected AOP exception", ex); |
71 | } |
72 | } |
Spring 中 Enhancer 的生成过程,我们可以通过 Enhancer的相关只是了解每个步骤的作用,这里有一步最重要的方法是 getCallbacks 方法设置拦截器:
1 | private Callback[] getCallbacks(Class<?> rootClass) throws Exception { |
2 | // 对于expose-proxy 的处理 |
3 | // Parameters used for optimisation choices... |
4 | boolean exposeProxy = this.advised.isExposeProxy(); |
5 | boolean isFrozen = this.advised.isFrozen(); |
6 | boolean isStatic = this.advised.getTargetSource().isStatic(); |
7 | |
8 | // 将拦截器封装在 DynamicAdvisedInterceptor中 |
9 | // Choose an "aop" interceptor (used for AOP calls). |
10 | Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised); |
11 | |
12 | // Choose a "straight to target" interceptor. (used for calls that are |
13 | // unadvised but can return this). May be required to expose the proxy. |
14 | Callback targetInterceptor; |
15 | if (exposeProxy) { |
16 | targetInterceptor = isStatic ? |
17 | new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) : |
18 | new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()); |
19 | } |
20 | else { |
21 | targetInterceptor = isStatic ? |
22 | new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) : |
23 | new DynamicUnadvisedInterceptor(this.advised.getTargetSource()); |
24 | } |
25 | |
26 | // Choose a "direct to target" dispatcher (used for |
27 | // unadvised calls to static targets that cannot return this). |
28 | Callback targetDispatcher = isStatic ? |
29 | new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp(); |
30 | |
31 | Callback[] mainCallbacks = new Callback[]{ |
32 | // 将拦截器加入到 Callback中 |
33 | aopInterceptor, // for normal advice |
34 | targetInterceptor, // invoke target without considering advice, if optimized |
35 | new SerializableNoOp(), // no override for methods mapped to this |
36 | targetDispatcher, this.advisedDispatcher, |
37 | new EqualsInterceptor(this.advised), |
38 | new HashCodeInterceptor(this.advised) |
39 | }; |
40 | |
41 | Callback[] callbacks; |
42 | |
43 | // If the target is a static one and the advice chain is frozen, |
44 | // then we can make some optimisations by sending the AOP calls |
45 | // direct to the target using the fixed chain for that method. |
46 | if (isStatic && isFrozen) { |
47 | Method[] methods = rootClass.getMethods(); |
48 | Callback[] fixedCallbacks = new Callback[methods.length]; |
49 | this.fixedInterceptorMap = new HashMap<String, Integer>(methods.length); |
50 | |
51 | // TODO: small memory optimisation here (can skip creation for methods with no advice) |
52 | for (int x = 0; x < methods.length; x++) { |
53 | List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass); |
54 | fixedCallbacks[x] = new FixedChainStaticTargetInterceptor( |
55 | chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass()); |
56 | this.fixedInterceptorMap.put(methods[x].toString(), x); |
57 | } |
58 | |
59 | // Now copy both the callbacks from mainCallbacks |
60 | // and fixedCallbacks into the callbacks array. |
61 | callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length]; |
62 | System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length); |
63 | System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length); |
64 | this.fixedInterceptorOffset = mainCallbacks.length; |
65 | } |
66 | else { |
67 | callbacks = mainCallbacks; |
68 | } |
69 | return callbacks; |
70 | } |
spring 在callBack 中考虑了很多情况,但是对于我们而言,只需要了解最长用的就可以了。比如将advised 属性封装在 DynamicAdvisedInterceptor中,并加入到callbacks中。
我们了解到CGLIB 对与方法中的拦截器是通过将自定义的拦截器(实现MethodInterceptor接口)加入 Callback中并且在调用代理的时候直接激活拦截器中的intercept方法来实现的,那么在getCallback中正是实现了这样一个目的。 DynamicAdvisedInterceptor 继承自MethodInterceptor, 加入 Callback后,再次调用地理时,会直接调用DynamicAdvisedInterceptor 中的 intercept方法, 由此判断,对于CGLIB 方式实现的代理,其核心逻辑是必然在 DynamicAdvisedInterceptor#intercept中
1 | //DynamicAdvisedInterceptor |
2 |
|
3 | public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { |
4 | Object oldProxy = null; |
5 | boolean setProxyContext = false; |
6 | Class<?> targetClass = null; |
7 | Object target = null; |
8 | try { |
9 | if (this.advised.exposeProxy) { |
10 | // Make invocation available if necessary. |
11 | oldProxy = AopContext.setCurrentProxy(proxy); |
12 | setProxyContext = true; |
13 | } |
14 | // May be null. Get as late as possible to minimize the time we |
15 | // "own" the target, in case it comes from a pool... |
16 | target = getTarget(); |
17 | if (target != null) { |
18 | targetClass = target.getClass(); |
19 | } |
20 | //获取拦截器 |
21 | List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); |
22 | Object retVal; |
23 | // Check whether we only have one InvokerInterceptor: that is, |
24 | // no real advice, but just reflective invocation of the target. |
25 | if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) { |
26 | // We can skip creating a MethodInvocation: just invoke the target directly. |
27 | // Note that the final invoker must be an InvokerInterceptor, so we know |
28 | // it does nothing but a reflective operation on the target, and no hot |
29 | // swapping or fancy proxying. |
30 | // 如果拦截器链为空,则直接激活方法 |
31 | retVal = methodProxy.invoke(target, args); |
32 | } |
33 | else { |
34 | // 进入链后,再激活方法 |
35 | // We need to create a method invocation... |
36 | retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed(); |
37 | } |
38 | retVal = processReturnType(proxy, target, method, retVal); |
39 | return retVal; |
40 | } |
41 | finally { |
42 | if (target != null) { |
43 | releaseTarget(target); |
44 | } |
45 | if (setProxyContext) { |
46 | // Restore old proxy. |
47 | AopContext.setCurrentProxy(oldProxy); |
48 | } |
49 | } |
50 | } |
与JDK 代理的实现方式大同小异,都是先构造链,然后封装此链进行串联调用。 稍有不同是:JDK 动态代理中直接构造ReflectMethodInvocation,而在 CGLIB 动态代理中,使用 CglibMethodInvocation。 CglibMethodInvocation 继承自ReflectMethodInvocation,但是proceed方法并没有重写。
Spring静态代理
静态代理主要是在虚拟机启动时,通过改变目标对象字节码的方式来完成目标对象的增强,它与动态代理相比,有更高的效率。因为在动态代理的过程中,还需要一个创建动态代理并且代理目标对象的步骤,而静态代理,则在启动时,完成了字节码的增强,当系统再次目标类时,与正常的类并无差别,所以在使用效率上会相对高些。
instrumentation
java 在1.5 版本时引入java.lang.instrument,你可以由此生成一个java agent,通过此agent 来修改类的字节码,即改变一个类。
我们通过 java instrument 来实现一个简单的java profiler。当然 instrument并不仅限于 profiler, instrument 还可以做很多事情,它类似于一种更低级,更松耦合的aop,可以从底层来改变一个类的行为。
具体细节略