SpringAOP实现原理

2019-09-15  本文已影响0人  刘一一同学

1. 概述

SpringAOP(Aspect Orient Programming)是一种设计思想,称为面向切面编程,利用横切技术剖析对象内部,将业务之间共同调用的逻辑提取并封装为一个可复用的模块,这个模块被命名为切面(Aspect),该模块减少系统中的重复代码,降低模块间的耦合度,可用于日志、权限认证、事务管理等。

SpringAOP思想的实现一般都是基于代理模式 ,在Java中采用JDK动态代理模式,但是JDK动态代理模式只能代理接口而不能代理类。因此SpringAOP会在CGLIBJDK动态代理之间进行切换。

2. 代理类型

SpringAOP的实现是基于代理模式 ,代理类型包括:静态代理、动态代理。

2.1 静态代理

AspectJ编译时增强)使用的是静态代理。所谓静态代理指的是,AOP框架会在编译阶段生成AOP代理类,它会在编译阶段将AspectJ植入到Java字节码中,运行的时候就是增强后的AOP对象。

AspectJ实现方式上依赖于特殊的AJC编译器,它并非是SpringAOP框架的一部分,而是SpringAOP使用了AspectJ的Annotation(注解),用来定义切面、切点等功能。

2.2 动态代理

SpringAOP使用的是动态代理。所谓动态代理指的是,AOP框架不会去修改字节码,而是每次运行时在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。

2.2.1 JDK动态代理

JDK动态代理要求被代理类必须实现一个接口,核心是InvocationHandler接口和Proxy类。JDK动态代理调用了Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h),通过该方法生成字节码,动态的创建一个代理类。interfaces参数是该动态类所继承的所有接口,而继承InvocationHandler接口的类则是实现在调用代理接口方法前后的具体逻辑。当

我们调用代理类对象的方法时,都会委托到InvocationHandler.invoke(Object proxy, Method method, Object[] args)方法,代理类对象作为proxy参数传入,参数method标识了我们具体调用的是代理类的哪个方法,args为这个方法的参数。

public interface PersonService {
    void speak(String content);
}

public class UserServiceImpl implements PersonService {
    @Override
    public void speak(String content) {
        System.out.println("speak被调用了===" + content);
    }
}

public class JDKProxy implements InvocationHandler {
    private Object proxy;
    public JDKProxy(Object proxy) {
        this.proxy = proxy;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object object = method.invoke(this.proxy, args);
        return object;
    }
    public static void main(String[] args) {
        PersonService person = (PersonService) Proxy.newProxyInstance(PersonService.class.getClassLoader(), 
                new Class[]{PersonService.class}, new JDKProxy(new UserServiceImpl()));
        person.speak("我是用户");
    }
}
2.2.2 CGLIB动态代理

CGLIB(Code Generation Library)底层使用了ASM(一个短小精悍的字节码操作框架)来操作字节码生成新的类,除了CGLIB库外,脚本语言(如Groovy何BeanShell)也使用ASM生成字节码。

CGLIB既能代理接口也能代理类,如果某个类被标记为final,是无法使用CGLIB做动态代理。

相关核心API:

2.3 何时使用JDK动态代理还是CGLIB?

如果目标类没有实现接口,那么SpringAOP会选择使用CGLIB动态代理目标类

3. 相关术语

4. 织入方式

5. 通知类型

  1. 前置通知(Before):在目标方法被调用之前调用通知功能;
  2. 后置通知(After):在目标方法执行完成之后调用通知,此时不会关心方法的输出是什么;
  3. 返回通知(After-returning):在目标方法成功执行之后调用通知;
  4. 异常通知(After-throwing):在目标方法抛出异常后调用通知;
  5. 环绕通知(Around):在被通知的方法调用之前和调用之后执行自定义的行为。

6. 事务的特性

  1. 原子性(Atomacity):事务包含的操作要么全部成功,要么全部失败,即使回滚也不会对数据库产生影响。
  2. 一致性(Consistency):事务必须使数据从一个一致性状态变换到另一个一致性状态,也就是说当一个系统在一致状态下更新后,系统中所有数据都保持一致。
  3. 隔离性(Isolation):当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间相互隔离。
  4. 持久性(Durability):事务一旦被提交,对数据库中的数据的改变就是永久性的,即使数据库系统遇到故障也不会丢失提交事务的操作。

7. 事务的隔离级别

8. 事务的传播行为

9. 事务的管理方式

Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,Spring是无法提供事务功能的。真正的数据库层的事务提交和回滚是通过binlog或者redo log实现的。

上一篇 下一篇

猜你喜欢

热点阅读