Spring AOP 从代理说起

186 阅读4分钟

1、什么是代理?

代理(Proxy) 是一种设计模式, 提供了对目标对象另外的访问方式;即通过代理访问目标对象。 这样好处: 可以在目标对象实现的基础上,增强额外的功能操作。(扩展目标对象的功能)。

1.1 静态代理

静态代理就是在DAO层以外加一个Proxy代理层,让代理层去重写DAO层的代码,而不需要在DAO层重复的编写

public class UserDaoProxy implements IUserDao{
// 接收保存目标对象【真正做事的还是UserDao】,因此需要维护userDao的引用
private IUserDao target;
public UserDaoProxy(IUserDao target) {
    this.target = target;
}
​
@Override
public void save() {
    System.out.println("开始时间...");
​
    target.save();          // 执行目标对象的方法
​
    System.out.println("结束时间...");
}
}

调用时调用代理层,而不是直接调用DAO层

public static void main(String[] args) {
    // 目标对象
    IUserDao target = new UserDao();
​
    // 代理
    IUserDao proxy = new UserDaoProxy(target);
    proxy.save();  // 执行的是,代理的方法
}

总结:

1、如果接口改了,代理的也要跟着改

2、因为代理对象,需要与目标对象实现一样的接口。所以会有很多代理类,也存在重复编写。

1.2 动态代理

1.2.1JDK动态代理

Java提供了一个Proxy类,调用它的newInstance方法可以生成某个对象的代理对象,该方法需要三个参数:

  • ClassLoader:生成代理对象使用哪个类装载器【一般我们使用的是代理类的装载器】
  • Class<?>[] :生成哪个对象的代理对象,通过接口指定【指定要代理类的接口】
  • InvocationHandler:生成的代理对象的方法里干什么事【实现handler接口,我们想怎么实现就怎么实现】
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)

总结:

1、代理对象拥有目标对象相同的方法【因为参数二指定了对象的接口】

2、用户调用代理对象的什么方法,都是在调用处理器的invoke方法。

3、使用JDK动态代理必须要有接口【参数二需要接口】 (没有接口就不能实现JDK动态代理,cglib动态代理可无接口实现)

1.2.2 cglib动态代理

cglib代理也叫子类代理,从内存中构建出一个子类来扩展目标对象的功能

2、什么是Spring AOP?

Spring AOP(Aspect Oriented Programming 面向切面编程): 将相同逻辑的重复代码横向抽取出来,使用动态代理技术将这些重复代码织入到目标对象方法中,实现和原来一样的功能

2.1 Spring AOP术语

连接点(Join point): 能够被拦截的地方:Spring AOP是基于动态代理的,所以是方法拦截的。每个成员方法都可以称之为连接点

切点(Poincut): 具体定位的连接点:上面也说了,每个方法都可以称之为连接点,我们具体定位到某一个方法就成为切点。

  • Spring AOP提供了6种切点类型:静态方法、动态方法、注解、表达式、流程、复合切点等。

增强/通知(Advice): 表示添加到切点的一段逻辑代码,并定位连接点的方位信息

  • Spring AOP提供了5种Advice类型:前置(Before)、后置(After)、返回(AfterReturning)、异常(AfterThrowing)、环绕(AfterThrowing)

织入(Weaving):增强/通知添加到目标类的具体连接点上的过程。

引入/引介(Introduction): 允许我们向现有的类添加新方法或属性。是一种特殊的增强!

切面(Aspect): 切面由切点和增强/通知组成,它既包括了横切逻辑的定义,也包括了连接点的定义。(一般切面、切点切面、引介/引入切面)

总结:

1、AOP的底层实际上是动态代理,动态代理分成了JDK动态代理和CGLib动态代理。如果被代理对象没有接口,那么就使用的是CGLIB代理(也可以直接配置使用CBLib代理)

2、如果是单例的话,那我们最好使用CGLib代理,因为CGLib代理对象运行速度要比JDK的代理对象要快

3、AOP既然是基于动态代理的,那么它只能对方法进行拦截,它的层面上是方法级别的

4、无论经典的方式、注解方式还是XML配置方式使用Spring AOP的原理都是一样的,只不过形式变了而已。一般我们使用注解的方式使用AOP就好了。

5、注解的方式使用Spring AOP就了解几个切点表达式,几个增强/通知的注解就完事了,是不是贼简单...使用XML的方式和注解其实没有很大的区别,很快就可以上手啦。

6、引介/引入切面也算是一个比较亮的地方,可以用代理的方式为某个对象实现接口,从而能够使用借口下的方法。这种方式是非侵入式的~

7、要增强的方法还可以接收与被代理方法一样的参数、绑定被代理方法的返回值这些功能...

\