Spring AOP 动态代理机制

Spring AOP的动态代理有两种:一是JDK的动态代理;另一个是cglib动态代理(通过修改字节码来实现代理)。

今天主要讨论JDK动态代理的方式。

JDK的代理方式主要就是通过反射跟动态编译来实现的,主要实现InvocationHandler接口和生成Proxy对象。

(1)定义AOP切面,实现InvocationHandler接口
(里面重载invoke方法,虚拟机自动调用此方法)

(2)创建代理类(通过java API)
假设被代理的类为Tagert,则

Target t = (Target)Proxy.newProxyInstance(字节码加载器, 需要代理的接口, 切面Advice);

请看demo:

public interface IBusiness {
    public void doBusiness();
}
public class Business implements IBusiness {

    public void doBusiness() {
        System.out.println("执行业务逻辑");
    }
}    
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class DynamicProxyDemo {

    public static void main(String[] args) {
        // 需要代理的接口,被代理类实现的多个接口都必须在这里定义
        Class[] proxyInterface = new Class[] { IBusiness.class};
        // 构建AOP的Advice,这里需要传入业务类的实例
        LogInvocationHandler handler = new LogInvocationHandler(new Business());
        // 生成代理类的字节码加载器
        ClassLoader classLoader = DynamicProxyDemo.class.getClassLoader();
        // 织入器,织入代码并生成代理类
        IBusiness proxyBusiness = (IBusiness) Proxy.newProxyInstance(
                classLoader, proxyInterface, handler);
        // 使用代理类的实例来调用方法。
        ((IBusiness) proxyBusiness).doBusiness();
    }

    /**
     * 打印日志的切面
     */
    public static class LogInvocationHandler implements InvocationHandler {

        private Object target; // 目标对象

        LogInvocationHandler(Object target) {
            this.target = target;
        }

        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            // 执行原有逻辑
            Object rev = method.invoke(target, args);
            // 执行织入的日志,你可以控制哪些方法执行切入逻辑
            if (method.getName().equals("doBusiness")) {
                System.out.println("记录日志");
            }
            return rev;
        }
    }
}

输出结果为:

执行业务逻辑
记录日志

可以看出,目标对象作为代理对象的一个属性,具体接口实现中,可以在调用目标对象相应方法前后加上其他业务处理逻辑。

一些知识:
1、静态代理和动态代理代理的区别:
静态代理:事先写好代理对象类,在程序发布前就已经存在了。
动态代理:应用程序发布后,通过动态创建代理对象。

2、JDK动态代理和CGLIB代理生成的区别
JDK动态代理只能对实现了接口的类生成代理。
CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法 。因为是继承,所以该类或方法最好不要声明成final ,final可以阻止继承和多态。

你可能感兴趣的:(spring)