spring-framework源码——AOP

代码Github地址:https://github.com/abelzha/spring-framework
代码包含springframework 5.2.0.BUILD-SNAPSHOT版本源码

1. 示例代码

业务类aspectdemo.Person.java

package aspectdemo;

import org.springframework.stereotype.Component;

@Component
public class Person{
	private String name;
	public String getPersonName(){
		System.out.println("-------getPersonName-------:"+ name);
		return name;
	}

	public boolean setPersonName(String name){
		System.out.println("--------setPersonName------:"+name);
		this.name = name;
		return true;
	}
}

切面类aspectdemo.PersonServiceLogAspect.java

package aspectdemo;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;

@Aspect
@Component
public class PersonServiceLogAspect {
	@Pointcut("execution(* aspectdemo.Person.*(..))")
	public void Log(){
	}

	@Before("Log()")
	public  void getLogBefore(JoinPoint point){
		System.out.println(point.getSignature().getName()+"-----getLogBefore,params:"+ Arrays.asList(point.getArgs()));
	}

	@AfterReturning(value = "Log()", returning ="result")
	public  void getLogAfter(JoinPoint point, Object result){
		System.out.println(point.getSignature().getName()+"------getLogAfter,result:"+ result);
	}
}

配置类aspectdemo.AspectAppConfig.java

package aspectdemo;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@EnableAspectJAutoProxy
@Configuration
@ComponentScan("aspectdemo")
public class AspectAppConfig{

}

启动类aspectdemo.AspectMain.java

package aspectdemo;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import java.util.Arrays;

public class AspectMain {
	public static void main(String[] args) {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AspectAppConfig.class);
		System.out.println(Arrays.asList(context.getBeanFactory().getBeanDefinitionNames()).toString().replaceAll(",", "\n"));
		Person person = context.getBean(Person.class);
		person.setPersonName("KAKA");
		context.close();
	}
}

在这里插入图片描述
以上是全部的示例代码,主要分析的有两点:
1、配置类上的注解@EnableAspectJAutoProxy做了什么?
2、启动类中person.setPersonName(“KAKA”);调用时,怎样执行了切点方法?
分析完以上两点就能大致了解AOP是如何工作的。

2.配置类上的注解@EnableAspectJAutoProxy做了什么?

在这里插入图片描述
1.@EnableAspectJAutoProxy导入了AspectJAutoProxyRegistrar.class。而该类中只有一个方法org.springframework.context.annotation.AspectJAutoProxyRegistrar#registerBeanDefinitions,老方法,打断点,查看容器启动时的调用栈。

调用过程:

  • 1.容器创建,调用容器刷新接口refresh();

  • 2.调用工厂后置处理器方法invokeBeanFactoryPostProcessors(beanFactory);

  • 3.被org.springframework.context.annotation.internalConfigurationAnnotationProcessor这个工厂的后置处理器处理,调用工厂后置处理器的方法:postProcessor.postProcessBeanDefinitionRegistry(registry);

  • 4.通过ConfigurationClassParser parser解析器来解析每一个@Configuration配置类,获取配置类中解析到的所有bean;
    Set configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
    loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);

  • 5.从配置类中加载导入的BeanDefinitionRegistrars信息。loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());

  • 6.创建注册AspectJAnnotationAutoProxyCreator, AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

至此,注解@EnableAspectJAutoProxy就是在容器中注册了一个AspectJAnnotationAutoProxyCreator。
AspectJAnnotationAutoProxyCreator ——>AbstractAdvisorAutoProxyCreator ——> AbstractAutoProxyCreator ---->SmartInstantiationAwareBeanPostProcessor ——>InstantiationAwareBeanPostProcessor ——>BeanPostProcessor

接下就是Person实例创建过程中,AspectJAnnotationAutoProxyCreator做了哪些事情?通过之前的分析我们得知了它是一个beanPostProcessor。所以它的调用时机也许我们能猜得到。

接下来,同样查看调用栈
在这里插入图片描述
有调用栈得知在实例化bean之后调用bean的后置处理器
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

for (BeanPostProcessor processor : getBeanPostProcessors()) {
	Object current = processor.postProcessAfterInitialization(result, beanName);
	if (current == null) {
		return result;
	}
	result = current;
}

上面代码就会调用AspectJAnnotationAutoProxyCreator的父类org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator的方法wrapIfNecessary。
1.得到bean中的切面(getAdvicesAndAdvisorsForBean),有两个是我们添加的,一个是容器默认添加的。
在这里插入图片描述

Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
2.通过new ProxyFactory();得到代理对象

  • 包装切面的allInterceptors得到bean中的增强器advisors;
  • 通过 return new ObjenesisCglibAopProxy(config);得到代理对象;
  • 返回wrappedBean,注册到容器中

以上,分析了注解@EnableAspectJAutoProxy的全部功能。

3. 启动类中person.setPersonName(“KAKA”);调用时,怎样执行了切点方法?

老办法:切面方法打断点,查看调用栈
在这里插入图片描述

retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
里面就是交给CglibAopProxy去控制MethodInterceptor和目标方法的执行。具体动态代理的详情以后再分析。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值