1、Spring AOP

1、Spring AOP

面向切面编程,是OOP面向对象编程的补充和完善

通过抽取一些系统级(非业务代码)的功能,以达到解耦和重复利用,如日志、事务、权限、缓存等

2、AOP相关概念

  1. 横切关注点
    对哪些方法在什么时候进行拦截,拦截后怎么处理,这些被称为横切关注点

  2. Aspect(切面)
    类时对象的抽象,切面就是横切关注点的抽象,把非业务代码功能放到一个类中形成切面,包含切入点、通知

  3. Pointcut(切入点)
    对连接点进行拦截的定义,在程序中主要体现为书写切入点表达式,在哪里

  4. Advice(通知)
    有before(前置),after(后置),afterReturning(最终),afterThrowing(异常),around(环绕),什么时间拦截到连接点之后需要执行的代码—非业务逻辑实现

  5. JointPoint(连接点)
    程序执行过程中明确的点,一般是方法的调用或异常抛出。

  6. weave(织入)
    将切面应用到目标对象并导致动态代理对象创建的过程,spring在运行时织入

  7. introduction(引入):
    在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段

  8. AOP代理(AOP Proxy):
    AOP框架创建的对象,代理就是目标对象的加强。Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于类

  9. 目标对象(Target Object):
    被代理对象,POJO

Advice通知类型

  1. Before: 在目标方法被调用之前做增强处理,@Before只需要指定切入点表达式即可
  2. AfterReturning: 在目标方法正常完成后做增强,@AfterReturning除了指定切入点表达式后,还可以指定一个返回值形参名returning,代表目标方法的返回值
  3. AfterThrowing: 主要用来处理程序中未处理的异常,@AfterThrowing除了指定切入点表达式后,还可以指定一个throwing的返回值形参名,可以通过该形参名来访问目标方法中所抛出的异常对象
  4. After:在目标方法完成之后做增强,无论目标方法时候成功完成。@After可以指定一个切入点表达式
  5. Around:环绕通知,在目标方法完成前后做增强处理,环绕通知是最重要的通知类型,像事务,日志等都是环绕通知

3、四种使用AOP的方式

  1. 经典的基于代理的AOP
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  2. 通过AspectJ提供的注解实现AOP
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  3. 通过AspectJ的XML方式实现AOP
    在这里插入图片描述
    在这里插入图片描述
  4. 基于Scheme-base的AOP
    在这里插入图片描述
    在这里插入图片描述
    SpringBoot中使用AOP
    @EnableAspectJAutoProxy开启AspectJ注解功能,使用@Aspect、@Before、@After等等,参考上面【AspectJ注解使用AOP】

         自定义注解+AspectJ实现AOP
在这里插入图片描述
在这里插入图片描述
4、AspectJ和Spring AOP
AspectJ:
AspectJ 在编译时自动编译得到了一个新类,这个新类增强了原有的类的功能,因此 AspectJ 通常被称为编译时增强的 AOP 框架,称为静态代理。

Spring AOP:
与 AspectJ 相同的是,Spring AOP 同样需要对目标类进行增强,也就是生成新的 AOP 代理类;与 AspectJ 不同的是,Spring AOP 无需使用任何特殊命令对 Java 源代码进行编译,它采用运行时动态地、在内存中临时生成“代理类”的方式来生成 AOP 代理,称为动态代理。

Spring 允许使用 AspectJ Annotation 用于定义方面(Aspect)、切入点(Pointcut)和增强处理(Advice),Spring 框架则可识别并根据这些 Annotation 来生成 AOP 代理。Spring 只是使用了和 AspectJ 5 一样的注解,但并没有使用 AspectJ 的编译器或者织入器(Weaver),底层依然使用的是 Spring AOP,依然是在运行时动态生成 AOP 代理,并不依赖于 AspectJ 的编译器或者织入器。

5、expose-proxy作用

public interface UserService{
	public void a();
	public void b();
}

public class UserServiceImpl implements UserService{
	@Transactional(propagation = Propagation.REQUIRED)
	public void a(){
		this.b();
	}
	@Transactional(propagation = Propagation.REQUIRED_NEW)
	public void b(){
		System.out.println("b has been called");
	}
}

a的事务会生效,b中不会有事务,因为a中调用b属于内部调用,没有通过代理,所以不会有事务产生。

如何设置b中事务也生效,如下:
<aop:aspectj-autoproxy expose-proxy=“true”>
expose-proxy设置为true,将代理暴露出来,使用AopContext.currentProxy()获取当前代理,将this.b()改为((UserService) AopContext.currentProxy()).b()。

6、Spring AOP底层原理分析
AOP动态代理(运行时生成、目标类的增强)

2种生成方式:
JDK
类实现了接口,代理类同样实现接口,代理其中的方法,如果有方法不在接口中定义的话就无法代理这个方法;

CGLIB
类没有实现接口,字节码增强技术,通过继承生成该类的子类, 类和方法不要声明为final

从源码可知,spring aop使用哪种方式依赖proxyTargetClass变量,如果为true则按照类是否实现接口选择JDK和CGLIB;如果为false则直接使用JDK(默认)。
配置proxyTargetClass值:
<aop:config proxy-target-class=“true”>
@EnableAspectJAutoProxy(proxyTargetClass=true)
在这里插入图片描述
源码跟踪:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
singletonObjects是缓存,map结构,存放完全初始化好的单例bean(代理对象)

singletonObjects缓存数据在初始化spring容器时就已经放进去了,如:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
BeanPostProcessor关于aop代理生成的是AbstractAutoProxyCreator
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值