SpringAop基于注解的源码解析
SpringAop基于注解的源码解析
1、简介
AOP 的全称是 “Aspect Oriented Programming”,即面向切面编程。在 AOP 的思想里面,周边功能(比如性能统计,日志,事务管理等)被定义为切面,核心功能和切面功能分别
独立进行开发,然后把核心功能和切面功能“编织”在一起,这就叫 AOP。AOP 能够将那些与业务无关,却为业务模块所共同调用的逻辑封装起来,便于减少系统的重复代码,降低模块间
的耦合度,并有利于未来的可拓展性和可维护性。
- 连接点(Join point):能够被拦截的地方,在Spring中,连接点主要指的是方法调用。Spring AOP 是基于动态代理的,每个成员方法都可以称之为连接点。
- 切点(Pointcut):每个方法都可以称之为连接点,我们定位到具体某一个或一些方法就称为切点。
- 增强/通知(Advice):表示添加到切点的一段逻辑代码,并定位连接点的方位信息,简单来说就定义了是干什么的,具体是在哪干。
- 织入(Weaving):将增强/通知添加到目标类的具体连接点上的过程。
- 引入/引介(Introduction):允许我们向现有的类添加新方法或属性,是一种特殊的增强。
- 切面(Aspect):切面由切点和增强/通知组成,它既包括了横切逻辑的定义、也包括了连接点的定义。
2、五种通知分类
1.前置通知(Before Advice):在目标方法被调用前调用通知功能。
2.后置通知(After Advice):是一种通用的后置通知,它会在目标方法正常完成(无论方法是否有返回值,也不管方法是否抛出了未被捕获的异常)后执行。
换句话说,只要方法执行完毕(无论以何种方式结束),对应的After Advice就会被触发。
特点:
独立于方法返回状态:无论方法是否成功返回一个值,或者是否抛出了异常,After Advice都会被执行。
无法访问方法返回值:由于这种通知类型并不关心方法的具体返回情况,因此在After Advice中无法直接访问到方法的返回值。通常用于资源清理、日志记录等场景:由于不依赖于方法执行
结果,After Advice适用于需要在方法执行结束后进行统一处理的任务,如关闭数据库连接、释放系统资源、记录方法执行耗时等与方法返回无关的操作。
3.返回通知(After-returning):是一种特殊的后置通知,它仅在目标方法成功执行且返回非null值之后才执行。也就是说,只有当方法没有抛出异常并且确实
返回了一个有效结果时,After-returning Advice才会被触发。由于可以访问到方法的返回值,After-returning Advice适合用于对方法返回结果进行
进一步加工、验证、缓存或者触发基于返回值的业务逻辑。
4.异常通知(After-throwing):在目标方法抛出异常之后调用通知功能。
5.环绕通知(Around):把整个目标方法包裹起来,在被调用前和调用之后分别调用通知功能。
3、AOP的使用示例
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.11</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.11</version>
</dependency>
3.1、创建AOP切面、配置切入点
@Aspect
@Component
public class AspectJTest {
@Pointcut("execution(public * com.dw.study.service.IOCService.hello(..))")
public void testAOP(){}
@Before("testAOP()")
public void before(){
System.out.println("before testAOP...");
}
@After("testAOP()")
public void after(){
System.out.println("after testAOP...");
}
@Around("testAOP()")
public Object around(ProceedingJoinPoint p){
System.out.println("around before testAOP...");
Object o = null;
try {
o = p.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
System.out.println("around after testAOP...");
return o;
}
}
3.2、创建业务类
public interface IOCService {
public String hello();
}
public class IOCServiceImpl implements IOCService {
@Override
public String hello() {
System.out.println("hello,IOC");
return "Hello,IOC";
}
}
@Configuration
@EnableAspectJAutoProxy
public class AnnotationConfig {
@Bean
public IOCService iocService() {
return new IOCServiceImpl();
}
}
// 测试
public static void main(String args[]) {
ApplicationContext context = new AnnotationConfigApplicationContext("com.dw.study.config");
IOCService iocService = context.getBean(IOCService.class);
iocService.hello();
}
3.3、运行结果
around before testAOP...
before testAOP...
hello,IOC
around after testAOP...
after testAOP...
详细的使用详解
4、源码解析
AOP实现的关键:
1、解析所有@Aspect注解的类,获取所有切入点(@Before、@After等通知注解)。
2、基于1中获取到的切入点,对每个bean,生成代理类。
从 @EnableAspectJAutoProxy 注解开始, 里面有一个@Import(AspectJAutoProxyRegistrar.class)。关于@Import注解,[可以参考之前的文章]。
主要作用是动态地往Spring IOC 中注册Bean。下面我们看 AspectJAutoProxyRegistrar 这个类。核心代码如下:
// 从这方法往下
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
// 找到调用的核心org.springframework.aop.config.AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(...)
// 这个方法主要往Spring IOC中注册了一个 AnnotationAwareAspectJAutoProxyCreator 这个是核心
registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source)
AnnotationAwareAspectJAutoProxyCreator 如何往Spring IOC中注册所有的切面并生成代理呢?
1、AnnotationAwareAspectJAutoProxyCreator的初始化?
可以看出它最终实现了InstantiationAwareBeanPostProcessor接口, 初始化工作在AbstractAutoProxyCreator类的postProcessBeforeInstantiation(...)方法中完成,这个方法在哪里调用的呢?
可以参考[InstantiationAwareBeanPostProcessor这个接口的执行流程]
接下来我们看看实例化的过程:
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
Object cacheKey = getCacheKey(beanClass, beanName);
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
// 重点看shouldSkip()这个方法
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// ....
org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator.shouldSkip()
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
// 获取所有切面
List<Advisor> candidateAdvisors = findCandidateAdvisors();
}
org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator.findCandidateAdvisors()
protected List<Advisor> findCandidateAdvisors() {
// 获取所有Beanfactory中所有的 Advisor
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
if (this.aspectJAdvisorsBuilder != null) {
// 从容器中取出所有的Bean, 如果类上面注解了@Aspect则进行处理
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder.buildAspectJAdvisors()
public List<Advisor> buildAspectJAdvisors() {
.....
// 如果类上注解了@Aspect则进行处理
if (this.advisorFactory.isAspect(beanType)) {
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
if (this.beanFactory.isSingleton(beanName)) {
// 找到所有Advisor并放入缓存中,在后置处理生成代理时中会用到
this.advisorsCache.put(beanName, classAdvisors);
}
...
}
.....
}
org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory.getAdvisors
@Override
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
List<Advisor> advisors = new LinkedList<>();
// getAdvisorMethods()获取切面Bean所有方法,并按照Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class) 顺序排序
for (Method method : getAdvisorMethods(aspectClass)) {
// 根据 method 构建Advisor
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
}
org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory.getAdvisor
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) {
// ....
// 创建Advisor实例化对象
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
....
// 实例化Advisor
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
// 具体实例化Advice
private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
return (advice != null ? advice : EMPTY_ADVICE);
}
// 具体实例化Advice
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
.....
// 根据不同的注解创建不同的Advice
AbstractAspectJAdvice springAdvice;
switch (aspectJAnnotation.getAnnotationType()) {
case AtBefore:
springAdvice = new AspectJMethodBeforeAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfter:
springAdvice = new AspectJAfterAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfterReturning:
springAdvice = new AspectJAfterReturningAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
springAdvice.setReturningName(afterReturningAnnotation.returning());
}
break;
case AtAfterThrowing:
springAdvice = new AspectJAfterThrowingAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
}
break;
case AtAround:
springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtPointcut:
if (logger.isDebugEnabled()) {
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
return null;
default:
throw new UnsupportedOperationException(
"Unsupported advice type on method: " + candidateAdviceMethod);
}
}
到这一步,前置处理已经完成, 找到所有的Advisor放入BeanFactoryAspectJAdvisorsBuilder的 advisorsCache = new ConcurrentHashMap<>();
2、后置处理-生成代理类
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
// 生成代理
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 根据当前Bean获取匹配到的Advisor
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 生成代理
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy
// 创建代理
org.springframework.aop.framework.ProxyCreatorSupport.createAopProxy
org.springframework.aop.framework.DefaultAopProxyFactory.createAopProxy
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
// 目标类是接口或者代理类,则使用 JDK 动态代理
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
// 使用CGLIB代理
return new ObjenesisCglibAopProxy(config);
} else {
return new JdkDynamicAopProxy(config);
}
}
}
// 获取代理对象(两种实现JDK代理、CGLIB代理)
org.springframework.aop.framework.ProxyFactory.getProxy(java.lang.ClassLoader)
3、调用逻辑参考
org.springframework.aop.framework.JdkDynamicAopProxy.invoke()
org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor.intercept()