spring aop
- 如何使用
- 纯pojo切面(xml)
- 注解驱动的切面
- AopNamespaceHandler
- 获取标签解析器
- 解析切面
- 解析通知
- 解析切点
- 代理类的创建
- 执行目标方法
源码大约分两步分,第一部分是在spring ioc初始化过程中加载所有aop标签到容器中,绑定代理类生成器AspectJAwareAdvisorAutoProxyCreator。
第二部分是在调用getBean实例化bean后,通过BeanPostProcessor的回调机制生成代理类。
如何使用
@Aspect
public class VocalConcert {
//定义一个切点,下面通知中可以直接使用,避免重复代码
@Pointcut("execution(* com.aop.test1.Song.song(..))")
public void doing() {
}
@Before("doing()")
public void checking() {
System.out.println("检票之后,找位子坐下");
}
@AfterReturning("doing()")
public void beautiful() {
System.out.println("演唱会进入精彩部分的时候,鼓掌!");
}
@AfterReturning("doing()")
public void leave() {
System.out.println("结束后,我们离开场地");
}
}
结合上面代码分析什么叫切面、切点、通知、引入?
切面:被声明为@Aspect的整个类VocalConcert叫做切面。
切点:@Pointcut该注解定义切点,用来指明要拦截的目标类的方法
通知:切面中定义的那些before、after等等逻辑可以叫做通知。
引入:上面涉及到所有的都是对类中方法的增加,引入是对类的增强
通知:通知包括以下几种:
1、前置通知
2、后置通知 在目标方法执行完之后执行
3、返回通知 在目标方法正常返回后执行,如果发生异常,目标方法没有返回,则不执行
4、异常通知
5、环绕通知 前置通知+后置通知
spring支持的4种aop类型:
1、经典spring aop:不在使用
2、AspectJ切面:和spring没有什么关系,AspectJ框架。可以对字段构造器等进行增强。不做深入学习。
3、纯pojo切面:基于aop的命名空间, 在xml中定义切面
4、注解驱动的切面:对纯pojo切面进行改进,不在xml中定义切面,通过声明切面类+注解
关注的是3和4,就是spring中传统的xml和注解两种方式。
纯pojo切面(xml)
1、定义切面类
public class SleepAspect {
public void before(){
System.out.println("睡觉之前拖衣服");
}
public void afterReturning(){
System.out.println("睡觉");
}
public void afterThrowing(Exception ex) throws Exception {
System.out.println("出大事了,有bug");
System.out.println(ex.getMessage());
}
public Object around(ProceedingJoinPoint pjp) throws Throwable{
Object proceed =null;
if (!"".equals("admin")){
System.out.println("核心方法被执行");
proceed = pjp.proceed(pjp.getArgs());
System.out.println("核心方法执行完");
}
return proceed;
}
}
2、声明目标类
3、xml中声明切面
注解驱动的切面
这种方式就是在纯pojo切面基础上通过注解进行改进,不用在xml中声明切面。
1、定义一个切面
@Aspect
public class VocalConcert {
//定义一个切点,下面通知中可以直接使用,避免重复代码
@Pointcut("execution(* com.aop.test1.Song.song(..))")
public void doing() {
}
@Before("doing()")
public void checking() {
System.out.println("检票之后,找位子坐下");
}
@AfterReturning("doing()")
public void beautiful() {
System.out.println("演唱会进入精彩部分的时候,鼓掌!");
}
@AfterReturning("doing()")
public void leave() {
System.out.println("结束后,我们离开场地");
}
}
2、开启切面功能
<?xml version="1.0" encoding="UTF-8"?>
//开启spring切面功能
返回顶部
AopNamespaceHandler
aop自定义标签解析器,用来解析aop自定义标签。
AopNamespaceHandler和aop标签是如何映射的?
xml中aop的命名空间 -- spring aop jar包下的META-INF下的spring.handlers。
AopNamespaceHandler :该类的init方法中绑定了几种aop标签对应的parser
public class AopNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
// In 2.0 XSD as well as in 2.1 XSD.
registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());//
registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
// Only in 2.0 XSD: moved to context namespace as of 2.1
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}
}
aop标签包含好几种,每一种都对应自己的parser,这种映射关系在上面AopNamespaceHandler的init方法中指定。具体标签包括哪些呢?
上面代码中:config、aspect等都属于aop标签。
返回顶部
获取标签解析器
回顾ioc初始化流程,
DefaultBeanDefinitionDocumentReader.parseBeanDefinitions:
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {//循环解析所有标签
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate);//默认标签
}
else {
delegate.parseCustomElement(ele);//自定义标签
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
//BeanDefinitionParserDelegate
public BeanDefinition parseCustomElement(Element ele) {
return parseCustomElement(ele, null);
}
public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
String namespaceUri = getNamespaceURI(ele);
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
//NamespaceHandlerSupport
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
return findParserForElement(element, parserContext).parse(element, parserContext);
}
private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
String localName = parserContext.getDelegate().getLocalName(element);
BeanDefinitionParser parser = this.parsers.get(localName);
if (parser == null) {
parserContext.getReaderContext().fatal(
"Cannot locate BeanDefinitionParser for element [" + localName + "]", element);
}
return parser;
}
首先获取标签解析器
因为aop最外层标签是config标签,所以先看下ConfigBeanDefinitionParser的parse方法
ConfigBeanDefinitionParser.parse:
public BeanDefinition parse(Element element, ParserContext parserContext) {
CompositeComponentDefinition compositeDef =
new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
parserContext.pushContainingComponent(compositeDef);
//向spring容器注册AspectJAwareAdvisorAutoProxyCreator
configureAutoProxyCreator(parserContext, element);
List 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;
}
1、向spring容器注册代理类生产器AspectJAwareAdvisorAutoProxyCreator
2、遍历所有aop标签下的所有子节点,分别定义三个入口,切面、切点、通知
返回顶部
解析切面
接下来该解析切面,注意,切面里边包含通知和切点,所以这个方法也包含了通知和切点的解析
ConfigBeanDefinitionParser.parseAspect:遍历所有aop标签,解析相应的通知和切点
private void parseAspect(Element aspectElement, ParserContext parserContext) {
String aspectId = aspectElement.getAttribute(ID);
String aspectName = aspectElement.getAttribute(REF);
try {
this.parseState.push(new AspectEntry(aspectId, aspectName));
List beanDefinitions = new ArrayList();
List beanReferences = new ArrayList();
List declareParents = DomUtils.getChildElementsByTagName(aspectElement, DECLARE_PARENTS);
for (int i = METHOD_INDEX; i < declareParents.size(); i++) {
Element declareParentsElement = declareParents.get(i);
beanDefinitions.add(parseDeclareParents(declareParentsElement, parserContext));
}
//获取切面所有子节点进行遍历
NodeList nodeList = aspectElement.getChildNodes();
boolean adviceFoundAlready = false;
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
if (isAdviceNode(node, parserContext)) {
if (!adviceFoundAlready) {
adviceFoundAlready = true;
if (!StringUtils.hasText(aspectName)) {
parserContext.getReaderContext().error(
" tag needs aspect bean reference via 'ref' attribute when declaring advices.",
aspectElement, this.parseState.snapshot());
return;
}
beanReferences.add(new RuntimeBeanReference(aspectName));
}
//如果标签是通知,进入解析通知标签方法
AbstractBeanDefinition advisorDefinition = parseAdvice(
aspectName, i, aspectElement, (Element) node, parserContext, beanDefinitions, beanReferences);
beanDefinitions.add(advisorDefinition);
}
}
AspectComponentDefinition aspectComponentDefinition = createAspectComponentDefinition(
aspectElement, aspectId, beanDefinitions, beanReferences, parserContext);
parserContext.pushContainingComponent(aspectComponentDefinition);
List pointcuts = DomUtils.getChildElementsByTagName(aspectElement, POINTCUT);
for (Element pointcutElement : pointcuts) {//获取切面下所有切点标签进行解析
//进入切点标签的解析方法入口
parsePointcut(pointcutElement, parserContext);
}
parserContext.popAndRegisterContainingComponent();
}
finally {
this.parseState.pop();
}
}
该方法拿到切面下所有的切点和通知标签进行遍历解析。切点调用parsePointcut解析,通知调用parseAdvice解析。
解析通知
//ConfigBeanDefinitionParser
private AbstractBeanDefinition parseAdvice(
String aspectName, int order, Element aspectElement, Element adviceElement, ParserContext parserContext,
List beanDefinitions, List beanReferences) {
try {
this.parseState.push(new AdviceEntry(parserContext.getDelegate().getLocalName(adviceElement)));
// create the method factory bean
RootBeanDefinition methodDefinition = new RootBeanDefinition(MethodLocatingFactoryBean.class);
methodDefinition.getPropertyValues().add("targetBeanName", aspectName);
methodDefinition.getPropertyValues().add("methodName", adviceElement.getAttribute("method"));
methodDefinition.setSynthetic(true);
// create instance factory definition
RootBeanDefinition aspectFactoryDef =
new RootBeanDefinition(SimpleBeanFactoryAwareAspectInstanceFactory.class);
aspectFactoryDef.getPropertyValues().add("aspectBeanName", aspectName);
aspectFactoryDef.setSynthetic(true);
// 声明通知为BeanDefinition
AbstractBeanDefinition adviceDef = createAdviceDefinition( //入口
adviceElement, parserContext, aspectName, order, methodDefinition, aspectFactoryDef,
beanDefinitions, beanReferences);
// 对上面创建的BeanDefinition包装一下
RootBeanDefinition advisorDefinition = new RootBeanDefinition(AspectJPointcutAdvisor.class);
advisorDefinition.setSource(parserContext.extractSource(adviceElement));
advisorDefinition.getConstructorArgumentValues().addGenericArgumentValue(adviceDef);
if (aspectElement.hasAttribute(ORDER_PROPERTY)) {
advisorDefinition.getPropertyValues().add(
ORDER_PROPERTY, aspectElement.getAttribute(ORDER_PROPERTY));
}
// register the final advisor
parserContext.getReaderContext().registerWithGeneratedName(advisorDefinition);
return advisorDefinition;
}
finally {
this.parseState.pop();
}
}
private AbstractBeanDefinition createAdviceDefinition(
Element adviceElement, ParserContext parserContext, String aspectName, int order,
RootBeanDefinition methodDef, RootBeanDefinition aspectFactoryDef,
List beanDefinitions, List beanReferences) {
//入口
RootBeanDefinition adviceDefinition = new RootBeanDefinition(getAdviceClass(adviceElement, parserContext));
adviceDefinition.setSource(parserContext.extractSource(adviceElement));
adviceDefinition.getPropertyValues().add(ASPECT_NAME_PROPERTY, aspectName);
adviceDefinition.getPropertyValues().add(DECLARATION_ORDER_PROPERTY, order);
if (adviceElement.hasAttribute(RETURNING)) {
adviceDefinition.getPropertyValues().add(
RETURNING_PROPERTY, adviceElement.getAttribute(RETURNING));
}
if (adviceElement.hasAttribute(THROWING)) {
adviceDefinition.getPropertyValues().add(
THROWING_PROPERTY, adviceElement.getAttribute(THROWING));
}
if (adviceElement.hasAttribute(ARG_NAMES)) {
adviceDefinition.getPropertyValues().add(
ARG_NAMES_PROPERTY, adviceElement.getAttribute(ARG_NAMES));
}
ConstructorArgumentValues cav = adviceDefinition.getConstructorArgumentValues();
cav.addIndexedArgumentValue(METHOD_INDEX, methodDef);
Object pointcut = parsePointcutProperty(adviceElement, parserContext);
if (pointcut instanceof BeanDefinition) {
cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcut);
beanDefinitions.add((BeanDefinition) pointcut);
}
else if (pointcut instanceof String) {
RuntimeBeanReference pointcutRef = new RuntimeBeanReference((String) pointcut);
cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcutRef);
beanReferences.add(pointcutRef);
}
cav.addIndexedArgumentValue(ASPECT_INSTANCE_FACTORY_INDEX, aspectFactoryDef);
return adviceDefinition;
}
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;
}
else {
throw new IllegalArgumentException("Unknown advice kind [" + elementName + "].");
}
}
该方法为每个通知实例化一个bean到spring容器。
不同类型的通知生成的RootBeanDifination的class属性不同
返回顶部
解析切点
//ConfigBeanDefinitionParser
private AbstractBeanDefinition parsePointcut(Element pointcutElement, ParserContext parserContext) {
String id = pointcutElement.getAttribute(ID);
String expression = pointcutElement.getAttribute(EXPRESSION);
AbstractBeanDefinition pointcutDefinition = null;
try {
this.parseState.push(new PointcutEntry(id));
//将pointcut创建成一个BeanDefinition
pointcutDefinition = createPointcutDefinition(expression);//入口
pointcutDefinition.setSource(parserContext.extractSource(pointcutElement));
String pointcutBeanName = id;
if (StringUtils.hasText(pointcutBeanName)) {
parserContext.getRegistry().registerBeanDefinition(pointcutBeanName, pointcutDefinition);
}
else {
pointcutBeanName = parserContext.getReaderContext().registerWithGeneratedName(pointcutDefinition);
}
parserContext.registerComponent(
new PointcutComponentDefinition(pointcutBeanName, pointcutDefinition, expression));
}
finally {
this.parseState.pop();
}
return pointcutDefinition;
}
protected AbstractBeanDefinition createPointcutDefinition(String expression) {
RootBeanDefinition beanDefinition = new RootBeanDefinition(AspectJExpressionPointcut.class);
beanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);
beanDefinition.setSynthetic(true);
beanDefinition.getPropertyValues().add(EXPRESSION, expression);
return beanDefinition;
}
为每个切点实例化一个bean到spring容器
返回顶部
代理类的创建
到这里,在ioc启动过程中,通过aop解析器把aop标签声明成BeanDefinition到spring容器中,已经完毕。
同时注意上面注册了一个类AspectJAwareAdvisorAutoProxyCreator,该类是BeanPostProcessor的下层类,同时封装了为普通bean生成代理类的方法。
这就意味着,在调用getBean获取bean实例之后,通过BeanPostProcessor的回调机制,通过spring容器中的相关aop标签和AspectJAwareAdvisorAutoProxyCreator类就可以创建代理类。
BeanPostProcessor回调为入口:
//AbstractAutoProxyCreator
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
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;
}
//判断是否需要生成代理类
//入口1
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = createProxy(//入口2 生成代理的方法
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
@Override
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
/***
* findEligibleAdvisors方法是拿当前Advisor对应的expression做了两层判断:
*
* 目标类必须满足expression的匹配规则
* 目标类中的方法必须满足expression的匹配规则,当然这里方法不是全部需要满足expression的匹配规则,有一个方法满足即可
*/
List advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
1、根据bean名称去spring容器获取所有的asvisor,注意:这个advisor包含切面和通知
2、匹配切点规则是否满足这个类,如果满足调用createProxy创建代理类
接下来就是创建代理类的方法
protected Object createProxy(
Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
// 1.创建proxyFactory,proxy的生产主要就是在proxyFactory做的
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
//这个节点中proxy-target-class="false"或者proxy-target-class不配置,即不使用CGLIB生成代理。
// 如果满足条件,进判断,获取当前Bean实现的所有接口,讲这些接口Class对象都添加到ProxyFactory中。
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
} else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 2.将当前bean适合的advice,重新封装下,封装为Advisor类,然后添加到ProxyFactory中
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
for (Advisor advisor : advisors) {
proxyFactory.addAdvisor(advisor);
}
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// 3.调用getProxy获取bean对应的proxy
return proxyFactory.getProxy(getProxyClassLoader());//入口
}
1、创建代理类工厂
2、将所有满足条件的advisor bean添加到代理工厂中
3、通过代理工厂创建代理类
public Object getProxy(ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);//入口1 + 入口2
}
1、通过createAopProxy选择是jdk还是cglib
2、通过getProxy创建代理类
// createAopProxy()方法就是决定究竟创建何种类型的proxy
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// 1.ProxyConfig的isOptimize方法为true,这表示让Spring自己去优化而不是用户指定
// 2、ProxyConfig的isProxyTargetClass方法为true,这表示配置了proxy-target-class="true"
// 3、ProxyConfig满足hasNoUserSuppliedProxyInterfaces方法执行结果为true,
// 这表示对象没有实现任何接口或者实现的接口是SpringProxy接口
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
// 2.如果目标类是接口或者是代理类,则直接使用JDKproxy
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
// 3.其他情况则使用CGLIBproxy
return new ObjenesisCglibAopProxy(config);
} else {
return new JdkDynamicAopProxy(config);
}
}
如果配置了就按照配置的选择,如果目标类是接口直接使用jdk代理
以jdk动态代理为例继续走下去。
public Object getProxy(ClassLoader classLoader) {
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
// JDK proxy 动态代理的标准用法
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
jdk动态代理创建。
返回顶部
执行目标方法
我们知道,jdk动态代理通过代理类调用目标方法的时候,实际调用的是自定义拦截器的invoke方法,aop的自定义拦截器为JdkDynamicAopProxy。
//知道,jdk动态代理通
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Class<?> targetClass = null;
Object target = null;
try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
return AopProxyUtils.ultimateTargetClass(this.advised);
}
//没有拦截器的时候,进入这个方法,直接通过反射调用目标方法
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);//入口1
}
Object retVal;
if (this.advised.exposeProxy) {//将代理类暴漏到AopContext中
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// 获取目标对象
target = targetSource.getTarget();
if (target != null) {
targetClass = target.getClass();
}
// 获取拦截器链 advisor
List
@Override
public Object proceed() throws Throwable {
// 从索引为-1的拦截器开始调用,按顺序递增,直到没有拦截器了,然后开始调用目标对象的方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
// 沿着定义好的拦截器链进行获取然后逐个处理
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// 这里是触发匹配判断的地方,如果和定义的pointcut匹配,那么这个advice将得到执行
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
return proceed();
}
}
else {
// 如果是一个interceptor,那么直接调用这个interceptor的invoke方法 进入此方法来分析通知(拦截器)是如何起作用的
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
@Override
public List
- 将所有的通知封装成一个拦截器链表,然后按顺序执行,最后通过反射调用目标方法
- AopContext内部通过ThreadLocal来存储了代理类,如果expose-proxy属性开启,这里还没将代理类放入到AopContext中。
返回顶部