基于注解的SpringAOP源码解析(一)

准备工作

本文会分析Spring的AOP模块的整体流程,分析过程需要使用一个简单的demo工程来启动Spring,demo工程我以备好,需要的童鞋自行在下方链接下载:

https://github.com/shiyujun/spring-framework
Demo工程示例代码

本文源码分析基于Spring5.0.0,所以pom文件中引入5.0的依赖

<dependencies>	
       <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>	
   </dependencies>

然后写一个简单的接口和实现类,跟IOC源码解析那几篇文章用的同一个工程,所以没有改名字

public interface IOCService {	
    public String hollo();	
}	

	
public class IOCServiceImpl implements IOCService {	
    public String hollo() {	
        return "Hello,IOC";	
    }	
}

增加bean的配置类,以及启动AOP

@EnableAspectJAutoProxy	
@Configuration	
public class AnnotationConfig {	
    @Bean	
    public IOCService iocService(){	
        return new IOCServiceImpl();	
    }	
}

创建切点

@Aspect	
@Component	
public class AspectJTest {	

	
    @Pointcut("execution(public * cn.shiyujun.service.IOCService.hollo(..))")	
    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;	
    }	
}

启动Spring

public class AnnotationIOCDemo {	
    public static void main (String args[]){	
        ApplicationContext context = new AnnotationConfigApplicationContext("cn.shiyujun.config");	
        IOCService iocService=context.getBean(IOCService.class);	
        System.out.println(iocService.hollo());	
    }	
}

至此,demo工程准备完毕。我就不详细的说明了,直接开始看源码吧

@EnableAspectJAutoProxy注解

可以看到,在最开始的demo工程中,为了开启AOP功能,我使用了一个@EnableAspectJAutoProxy注

进入这个注解可以查看到这个注解的2个属性,相信大家都已经很熟悉了,就不相信的说明了。除此之外可以看到这个注解使用@Import注解引入了一个配置类

@Import注解:可以引入一个类,将这个类注入到Spring IOC容器中被当前Spring管理

@Import(AspectJAutoProxyRegistrar.class)	
public @interface EnableAspectJAutoProxy {	
    //proxyTargetClass属性,默认false,尝试采用JDK动态代理织入增强(如果当前类没有实现接口则还是会使用CGLIB);如果设为true,则强制采用CGLIB动态代理织入增强	
    boolean proxyTargetClass() default false;	
    //通过aop框架暴露该代理对象,aopContext能够访问。为了解决类内部方法之间调用时无法增强的问题	
    boolean exposeProxy() default false;	
}

看一下这个配置类的操作

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {	
    AspectJAutoProxyRegistrar() {	
    }	

	
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {	
               //注册一个AOP代理实现的Bean,往下看          AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);	
        AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);	
        if (enableAspectJAutoProxy != null) {	
            if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {	
                AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);	
            }	

	
            if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {	
                AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);	
            }	
        }	

	
    }	
}

registerAspectJAnnotationAutoProxyCreatorIfNecessary方法的主要功能是注册或者升级AnnotationAwareAspectJAutoProxyCreator

这个类在AOP中非常的重要,它的主要功能就是根据@Point注解定义的切点来自动代理与表达式匹配的类。

private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {	
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); //如果已存在这个bean	
        if (registry.containsBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator")) {	
            BeanDefinition apcDefinition = registry.getBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator");	
            //判断优先级,如果优先级较高则替换原先的bean	
            if (!cls.getName().equals(apcDefinition.getBeanClassName())) {	
                int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());	
                int requiredPriority = findPriorityForClass(cls);	
                if (currentPriority < requiredPriority) {	
                    apcDefinition.setBeanClassName(cls.getName());	
                }	
            }	

	
            return null;	
        } else {	
            //注册AnnotationAwareAspectJAutoProxyCreator到容器中,此类负责基于注解的AOP动态代理实现	
            RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);	
            beanDefinition.setSource(source);	
            beanDefinition.getPropertyValues().add("order", -2147483648);	
            beanDefinition.setRole(2);	
            registry.registerBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator", beanDefinition);	
            return beanDefinition;	
        }	
    }

未完待续

640?wx_fmt=jpeg

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值