文章目录
- 开头
- aop:config
- 解析
- proxy-target-class & expose-proxy
- aop:pointcut
- aop:advisor
- aop:aspect
- aop:declare-parents
- 其它
- MethodLocatingFactoryBean
- SimpleBeanFactoryAwareAspectInstanceFactory
- 总结
- 代理子类生成
- 入口
- postProcessBeforeInstantiation
- 调用时机
- 源码
- 应该代理 ?
- 基础类检测
- 跳过类检测
- AOP逻辑
- Advisor寻找
- 适用性检测
- 检测结果缓存
- TargetSource
- postProcessAfterInitialization
- Advisor寻找
- 适用性判断
- 引入
- 其它
- Advisor扩展
- 排序
- 创建
- JDK动态代理 or Cglib
- JDK动态代理
- equals & hashCode
- 链式调用
- Cglib
开头
aop部分的解析器由AopNamespaceHandler注册,其init方法:
代码语言:javascript复制@Override
public void init() {
registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
}
aop:config
此标签用以配置pointcut, advisor, aspect,实例:
代码语言:javascript复制<aop:config>
<aop:pointcut expression="execution(* exam.service..*.*(..))" id="transaction"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="transaction"/>
<aop:aspect ref="" />
</aop:config>
ConfigBeanDefinitionParser.parse:
代码语言:javascript复制@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
CompositeComponentDefinition compositeDef =
new CompositeComponentDefinition(element.getTagName(),
parserContext.extractSource(element));
parserContext.pushContainingComponent(compositeDef);
// 是否生成代理类
configureAutoProxyCreator(parserContext, element);
List<Element> childElts = DomUtils.getChildElements(element);
for (Element elt: childElts) {
String localName = parserContext.getDelegate().getLocalName(elt);
if (POINTCUT.equals(localName)) {
parsePointcut(elt, parserContext);
} else if (ADVISOR.equals(localName)) {
parseAdvisor(elt, parserContext);
} else if (ASPECT.equals(localName)) {
parseAspect(elt, parserContext);
}
}
parserContext.popAndRegisterContainingComponent();
return null;
}
解析
解析的过程主要分为以下几个部分。
proxy-target-class & expose-proxy
对应着aop:config的两个属性,前者代表是否为被代理这生成CGLIB子类,默认false,只为接口生成代理子类(话说如果不生成子类那么怎么拦截?)。后者代表是否将代理bean暴露给用户,如果暴露,可以通过Spring AopContext类获得,默认不暴露。
解析的过程无非就是属性的读取,不再详细说明。
aop:pointcut
pointcut的解析是一个生成一个BeanDefinition并将其id, expression等属性保存在BeanDefinition中。注意以下几点:
- BeanDefinition的ID来自于id属性,如果没有,那么自动生成。
- BeanDefinition的class是AspectJExpressionPointcut。
- BeanDefinition的scope为prototype。
AspectJExpressionPointcut类图:
aop:advisor
首先是其所有属性的示例:
代码语言:javascript复制<aop:advisor id="" order="" advice-ref="aopAdvice" pointcut="" pointcut-ref="" />
advisor概念是Spring独有的,来自于上古时代,应该是较早时候的aop概念的实现: AOP Alliance (Java/J2EE AOP standards)。Spring官方的说法: aop-schema-advisors。
其相关的包/类就在spring-aop下:
advice-ref是必须的属性,并且这里的advice必须实现org.aopalliance.aop.Advice的子接口。这些子接口指的什么呢,见Spring官方文档: aop-api-advice-types。比如org.aopalliance.intercept.MethodInterceptor。
最常见的用途就是结合事务使用:
代码语言:javascript复制<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" read-only="true" propagation="NOT_SUPPORTED"/>
<tx:method name="find*" read-only="true" propagation="NOT_SUPPORTED"/>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut expression="execution(* exam.service..*.*(..))" id="transaction"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="transaction"/>
</aop:config>
解析的套路和楼上类似,只不过此处的beanClass是DefaultBeanFactoryPointcutAdvisor,其类图:
另外注意对于pointcut和pointcut-ref两者处理的区别,对于pointcut属性,Spring会同样创建一个AspectJExpressionPointcut类型的BeanDefinition,对于pointcut-ref会生成一个RuntimeBeanReference对象指向原pointcut的引用。此类的类图:
可以看出,这种aop的实现需要实现各种接口,所以不应该再使用此种方式进行aop,除了Spring内部的实现。
aop:aspect
配置举例:
代码语言:javascript复制<bean id="aopAdvice" class="base.aop.AopDemoAdvice" />
<!-- 必须配置,因为被代理的对象必须在Spring容器中 -->
<bean id="aopDemo" class="base.aop.AopDemo" />
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* base.aop.AopDemo.send())" />
<aop:aspect ref="aopAdvice">
<aop:before method="beforeSend" pointcut-ref="pointcut" />
<aop:after method="afterSend" pointcut-ref="pointcut" />
</aop:aspect>
</aop:config>
解析形成的BeanDefinition结构如下:
代码语言:javascript复制AspectComponentDefinition
beanRefArray
RuntimeBeanReference(aop:aspect的ref属性)
beanDefArray
// 被注册
RootBeanDefinition(aop:declare-parents)
beanClass: DeclareParentsAdvisor
ConstructorArg
implement-interface
types-matching
default-impl
delegate-ref
// 被注册
RootBeanDefinition(aop:before,aop:after...)
beanClass: AspectJPointcutAdvisor
ConstructorArg
RootBeanDefinition
beanClass: 由子标签决定
ConstructorArg
RootBeanDefinition
beanClass: MethodLocatingFactoryBean
properties
targetBeanName: aspectName
methodName: method属性
RootBeanDefinition
beanClass: SimpleBeanFactoryAwareAspectInstanceFactory
properties
aspectBeanName: aspectName
//还有pointcut定义和引用...
结构图里面的aspectName来自于aop:aspect的ref属性,此属性是必须配置的,因为Spring要知道aop:before等标签指定的方法是哪个bean/类/对象的方法。
aop:declare-parents
对于aop:declare-parents子标签,其决定的是代理子类应该实现哪些接口:
代码语言:javascript复制<aop:declare-parents types-matching="" implement-interface="" />
此标签最终被解析成为beanClass为DeclareParentsAdvisor的BeanDefinition,并注册到容器中。其类图:
其它
此处的其它指的是aop:before, aop:after等最核心的标签。其最终被解析为beanClass为AspectJPointcutAdvisor的BeanDefinition,类图:
正如上面结构图里所描述的,其构造参数为一个BeanDefintion,此对象的beanClass是不确定的,由aop:before/after中的before和after决定,代码:
代码语言:javascript复制private Class<?> getAdviceClass(Element adviceElement, ParserContext parserContext) {
String elementName = parserContext.getDelegate().getLocalName(adviceElement);
if (BEFORE.equals(elementName)) {
return AspectJMethodBeforeAdvice.class;
} else if (AFTER.equals(elementName)) {
return AspectJAfterAdvice.class;
} else if (AFTER_RETURNING_ELEMENT.equals(elementName)) {
return AspectJAfterReturningAdvice.class;
} else if (AFTER_THROWING_ELEMENT.equals(elementName)) {
return AspectJAfterThrowingAdvice.class;
} else if (AROUND.equals(elementName)) {
return AspectJAroundAdvice.class;
}
}
而此BeanDefintion的构造参数又由以下三个部分组成:
MethodLocatingFactoryBean
第一个便是beanClass为此类型的BeanDefinition。其内部有一个methodName属性,存储的便是标签的method属性的值。其类图:
这个东西是干什么用的呢?其实是用于在指定的advice(aop:aspect的ref属性)中得到Method对象。入口在setBeanFactory方法:
代码语言:javascript复制@Override
public void setBeanFactory(BeanFactory beanFactory) {
Class<?> beanClass = beanFactory.getType(this.targetBeanName);
this.method = BeanUtils.resolveSignature(this.methodName, beanClass);
}
SimpleBeanFactoryAwareAspectInstanceFactory
其类图:
此类用于在BeanFactory中定位aspect bean,这个bean指的是谁?
代码语言:javascript复制<bean id="aopAdvice" class="base.aop.AopDemoAdvice" />
就是它!查找很简单:
代码语言:javascript复制@Override
public Object getAspectInstance() {
return this.beanFactory.getBean(this.aspectBeanName);
}
总结
从整个aop:aspect标签最终被解析为一个AspectJPointcutAdvisor来看,Spring在实现上仍将其作为Advisor的概念。
代理子类生成
关键在于AspectJAwareAdvisorAutoProxyCreator,此对象在ConfigBeanDefinitionParser的configureAutoProxyCreator方法中注册,其类图:
那么子类生成的入口在哪里呢?
入口
从AspectJAwareAdvisorAutoProxyCreator的类图中可以看出,此类实现了SmartInstantiationAwareBeanPostProcessor接口,所以很容易想到入口应该位于此接口及其父接口(BeanPostProcessor)的相关方法中。实际上确实是这样的。
postProcessBeforeInstantiation
调用时机
先来回顾一下此方法在Bean创建的过程中的调用时机。
AbstractAutowireCapableBeanFactory.createBean部分源码:
代码语言:javascript复制 Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
可以看出,调用发生在Bean实例的创建之前。
源码
AbstractAutoProxyCreator.postProcessBeforeInstantiation:
代码语言:javascript复制@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
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;
}
下面分部分对其进行说明。
应该代理 ?
Spring首先会对当前的beanClass进行检查(是否应该/可以对其进行代理)。
不应该代理的类分为两种情况:
- 用于实现AOP的Spring基础类,此种情况在isInfrastructureClass方法中完成检测(单词Infrastructure正是基础设施的意思)。
- 子类定义的应该跳过的类,默认AbstractAutoProxyCreator的实现直接返回false,即都不应该跳过。
基础类检测
AbstractAutoProxyCreator.isInfrastructureClass:
代码语言:javascript复制protected boolean isInfrastructureClass(Class<?> beanClass) {
boolean retVal = Advice.class.isAssignableFrom(beanClass) ||
Pointcut.class.isAssignableFrom(beanClass) ||
Advisor.class.isAssignableFrom(beanClass) ||
AopInfrastructureBean.class.isAssignableFrom(beanClass);
return retVal;
}
可以看出,任何Advice、Pointcut、Advisor、AopInfrastructureBean的子类都被当做Spring实现AOP的基础设施类。
跳过类检测
即shouldSkip方法。前面提到了,AbstractAutoProxyCreator的默认实现直接返回fasle,这一特性被子类AspectJAwareAdvisorAutoProxyCreator重写:
代码语言:javascript复制@Override
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
List<Advisor> candidateAdvisors = findCandidateAdvisors();
for (Advisor advisor : candidateAdvisors) {
if (advisor instanceof AspectJPointcutAdvisor) {
if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {
return true;
}
}
}
return super.shouldSkip(beanClass, beanName);
}
那么此方法跳过的是谁呢?
其实就是我们通过aop:aspect标签配置的切面,即:
代码语言:javascript复制<bean id="aopAdvice" class="base.aop.AopDemoAdvice" />
<aop:config>
<aop:aspect ref="aopAdvice">
</aop:aspect>
</aop:config>
里的aopAdvice。
从前面的aop:aspect一节中可以知道,Spring对于aop:config的解析其实是把aop:before/after等标签解析成为了AspectJPointcutAdvisor类型的BeanDefinition,而aopAdvice以AbstractAspectJAdvice的类型保存在其中。
所以可以得出结论: Spring跳过的是适用于当前bean的Advisor的Advice/Aspect对象。
AOP逻辑
那么Spring又是如何找到适用于当前bean的Advisor的呢?
Advisor寻找
关键便是findCandidateAdvisors方法,此方法将逻辑委托给BeanFactoryAdvisorRetrievalHelper.findAdvisorBeans:
代码语言:javascript复制public List<Advisor> findAdvisorBeans() {
String[] advisorNames = null;
synchronized (this) {
// 结果缓存
advisorNames = this.cachedAdvisorBeanNames;
if (advisorNames == null) {
// 去容器中寻找
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
this.cachedAdvisorBeanNames = advisorNames;
}
}
if (advisorNames.length == 0) {
return new LinkedList<Advisor>();
}
List<Advisor> advisors = new LinkedList<Advisor>();
for (String name : advisorNames) {
if (isEligibleBean(name)) {
if (!this.beanFactory.isCurrentlyInCreation(name)) {
advisors.add(this.beanFactory.getBean(name, Advisor.class));
}
}
}
return advisors;
}
可以看出,首先是从容器中获取到所有的Advisor示例,然后调用isEligibleBean方法逐一判断Advisor是否适用于当前bean。
适用性检测
指的便是isEligibleBean方法。最终调用的是AbstractAdvisorAutoProxyCreator的同名方法:
代码语言:javascript复制protected boolean isEligibleAdvisorBean(String beanName) {
return true;
}
而AbstractAdvisorAutoProxyCreator的子类AspectJAwareAdvisorAutoProxyCreator并没有覆盖此方法,所以此处会对容器中所有的Advisor的Advice进行跳过。
检测结果缓存
因为postProcessBeforeInstantiation方法会在每个bean初始化之前被调用,所以没有必要每次都真的进行基础类检测和跳过类检测,Spring使用了advisedBeans作为缓存用以提高性能。
TargetSource
从源码中可以看出,对于自定义的TargetSource,Spring会立即执行代理子类的创建。Spring的代理其实是针对TargetSource的,其类图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C8HxE1LE-1632904951652)(images/TargetSource.jpg)]
关于此接口在此不展开叙述。
postProcessAfterInitialization
AbstractAutoProxyCreator.postProcessAfterInitialization:
代码语言:javascript复制@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
关键便在于wrapIfNecessary方法:
代码语言:javascript复制protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
//自定义TargetSource,已经进行过代理子类生成
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
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;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
可以看出,在此方法的开头又进行了基础类以及跳过类的检测,再次不再赘述。
Advisor寻找
即getAdvicesAndAdvisorsForBean方法,这里进行的便是去容器中寻找适用于当前bean的Advisor,最终调用的是
AbstractAdvisorAutoProxyCreator.findEligibleAdvisors:
代码语言:javascript复制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前面已经说过了。
适用性判断
findAdvisorsThatCanApply最终调用AopUtils.findAdvisorsThatCanApply:
代码语言:javascript复制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;
}
关键在于canApply方法,从源码中可以看出,对于Advisor的判断分为了IntroductionAdvisor以及非IntroductionAdvisor两种情况。
这种分开处理导致了IntroductionAdvisor在Advisor链中总是位于非IntroductionAdvisor前面。
canApply(candidate, clazz)其实等价于canApply(candidate, clazz, false):
代码语言:javascript复制public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// It doesn't have a pointcut so we assume it applies.
return true;
}
}
很明显,对于引入Advisor与其它Advisor是两种不同的判断方式。
引入
引入的概念在下面aop:scoped-proxy中有提到。因为引入的目的在于动态地向一个类添加另一种功能(接口),所以只要判断给定的类是否是要引入到的类即可。
其它
AopUtils.canApply:
代码语言:javascript复制public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
//是否Pointcut可以匹配当前类
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
MethodMatcher methodMatcher = pc.getMethodMatcher();
//是否Pointcut可以匹配所有方法
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;
}
}
}
return false;
}
Spring的Pointcut由ClassFilter和MethodMatcher两部分组成,其中前者用以判断给定的类是否在Pointcut的匹配范围内,后者用以在ClassFilter匹配满足的情况下判断给定的方法是否在Pointcut匹配的范围内。
从源码中可以看出,如果ClassFilter匹配得到满足并且Pointcut并不能匹配此类的任意方法,便会用反射的方法获取targetClass(被检测类)的全部方法逐一交由Pointcut的MethodMatcher进行检测。
关于Pointcut表达式是如何解析及存储的在此不再展开。
Advisor扩展
AbstractAdvisorAutoProxyCreator.extendAdvisors允许子类向Advisor链表中添加自己的Advisor。子类AspectJAwareAdvisorAutoProxyCreator重写了此方法,其逻辑是:
如果Advisor链表中的Advisor含有AspectJ Advice,那么将会把一个ExposeInvocationInterceptor添加到链表的表头,目的在于将MethodInvocation以ThreadLocal的方式暴露给后面所有的Advisor,暂不知道具体的用途。
排序
即sortAdvisors方法,用于对实现了Ordered接口的Advisor进行排序。
创建
AbstractAutoProxyCreator.createProxy(略去非关键代码):
代码语言:javascript复制protected Object createProxy(
Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
//将interceptor适配为Advisor
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
for (Advisor advisor : advisors) {
proxyFactory.addAdvisor(advisor);
}
return proxyFactory.getProxy(getProxyClassLoader());
}
JDK动态代理 or Cglib
由DefaultAopProxyFactory.createAopProxy方法决定使用何种方式创建代理子类。
代码语言:javascript复制@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() ||
hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
} else {
return new JdkDynamicAopProxy(config);
}
}
逻辑很明显,如果指定了(proxy-target-classs设为true)使用Cglib,那么就会使用Cglib的方式,如果没有指定(或为false),那么先回检测被代理类是否实现了自己的接口,如果实现了,那么就采用JDK动态代理的方式。
JDK动态代理
JdkDynamicAopProxy.getProxy:
代码语言:javascript复制@Override
public Object getProxy(ClassLoader classLoader) {
//找到可以用来进行代理的接口
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
//用来代理的接口中是否定义了equals或者是hashCode方法?
//结果保存在内部equalsDefined和hashCodeDefined两个成员变量中
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
可以看出,关键的InvocationHandler参数其实就是JdkDynamicAopProxy自身。
其invoke方法较长,源码就不贴了,下面进行分部分说明。
equals & hashCode
如果被代理类实现了equals或者是hashCode方法,那么生成的代理子类的equals、hashCode方法实际上执行的是JdkDynamicAopProxy相应方法的逻辑。
invoke方法部分源码:
代码语言:javascript复制if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
return equals(args[0]);
}
链式调用
对于切点方法,比如前面aop:aspect示例配置中的beforeSend
代码语言:javascript复制<aop:before method="beforeSend" pointcut-ref="pointcut" />
Spring会创建一个MethodInvocation对象对所有相关的Advisor进行链式调用。invoke相关源码:
代码语言:javascript复制List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
Object retVal = invocation.proceed();
Cglib
同样是对于Advisor的链式调用,不再详细展开。