欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

spring框架学习之路(一)-入门基础(2)-动态代理和AOP(面向切面编程)

程序员文章站 2022-05-24 23:43:39
...

  spring框架学习之路(一)-入门基础(1)-IOC(控制反转)&DI(依赖注入);
  之前写了关于spring的内核IOC&DI的一些内容,现在接着写spring的另一个重要概念AOP。
  AOP(Aspect Oriented Programming):面向切面编程。与OOP(面向对象编程)自上而下的程序结构不同的是,AOP是针对于程序切面。
  比如日志记录,我们需要对多个类中的多个方法执行前或执行后进行记录日志,如果我们对每一个方都添加相同的记录日志的代码,就违反了DRY(Don’t repeat yourself)原则。所以出现了AOP,AOP就是在程序的水平结构上进行整体程序设计,而不需要针对每一个方法进行设计。
  要了解AOP,就必须了解“代理模式”(不了解的百度吧…设计模式的坑以后填…),而AOP利用的就是“动态代理”。
  简单来说,AOP主要就是动态生成和不同的“真实角色”相对应的“代理角色”。核心就是InvocationHandler接口 和Proxy.newProxyInstance() 方法。
  老规矩,举个栗子~~~

//抽象角色
public interface AbsRole {  
    void doActive();
}
//真实角色
public class RealRole implements AbsRole {
    @Override
    public void doActive() {
        System.out.println("active from real role!");
    }
}

  然后创建一个InvocationHandler,InvocationHandler只有一个invoke()方法,而我们只需要在里面实现method.invoke(obj, args);就可以调用 对象obj的方法method,此方法参数为args,返回值为res。
  在这条语句前后加入逻辑,就可以实现每次执行方法method时都会附带执行前后逻辑。(这里就是前后的两条输出语句)

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class ProxyRole implements InvocationHandler {

    private Object obj;

    public ProxyRole(Object obj) {
        super();
        this.obj = obj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        System.out.println("previous method");
        Object res=method.invoke(obj, args);
        System.out.println("after method");
        return res;
    }   
}

main方法的执行方法为:

    public static void main(String[] args) {    
        RealRole real=new RealRole();       
        AbsRole abs=(AbsRole) Proxy.newProxyInstance(RealRole.class.getClassLoader(), RealRole.class.getInterfaces(), new ProxyRole(real));
        abs.doActive();
    }

大体逻辑执行过程就是:
  通过Proxy.newProxyInstance()方法生成一个对象,此对象继承$Proxy0类,并实现真实角色的接口,并且此对象拥有一个InvocationHandler h对象的应用。然后用一个抽象角色abs引用这个对象。
  执行abs.doActive()时,此对象在doActive()方法中的具体实现就是调用h.invoke()方法,这样在h.invoke()中就实现了对真实角色方法的执行。
  **另外需要注意的是,在ProxyRole类中
  public Object invoke(Object proxy, Method method, Object[] args)
  方法中的proxy对象不是真实角色的应用,而是动态生成的代理角色(就是那个继承自$Proxy0类的对象)的引用。**