aop的方式:
- 静态代理 : 直接修改原类,比如编译期生成代理类的 APT。
- 自定义类加载器:使用类加载器启动自定义的类加载器,并加一个类加载监听器,监听器发现目标类被加载时就织入切入逻辑,以 Javassist 为代表。
- 动态代理:字节码加载后,为接口动态生成代理类,将切面植入到代理类中,以 JDK Proxy 为代表。
- 动态字节码生成:字节码加载后,通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用织入逻辑。属于子类代理,以 CGLIB 为代表。
- 1、2为静态织入;3,4为动态织入。
AspectJ代理方式:
- 基于注解
- @Aspect
- @Pointcut 切入点
- @Before
- @After
- @Around 需要手动调用:joinPoint.proceed();
- 织入方式:
- ajc编译,编译期将切面织入业务代码中。
- aspectjweaver.jar 的agent代理,在类加载期间织入切面。
- 两者的优缺点:a方式,在反编译时,会看到织入的切面代码?
Spring AOP 动态代理
- 原理:采用截取的方式,对被代理类进行装饰,以取代原有对象的行为,不会产生新类。
- 使用AspectJ 的注解,但是织入时使用JDK或CGLib(可选配置),因此Spring AOP不是静态代理,而是动态代理。
- 缺点:不能修改对象字段;不支持构造器连接点,即无法在Bean创建时添加代理动作。(AspectJ可以)
使用Spring AOP
-
maven
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>${spring.version}</version> </dependency> 切面类上添加 @Aspect
切面类中,对应的方法上使用:@Before,@After,@Around......
切面类中,对应的方法上配置execution或@annotation
配置类中开启代理 @EnableAspectJAutoProxy