AOP实现(JDK动态代理和CGlib动态代理)

AOP(面向切面编程)的实现方式有多种,

  1. ajc编译器:可以通过aspectj-maven-plugin插件在编译期对原java文件的字节码进行修改。
  2. agent类加载:在类加载时完成方法增强,通过设置JVM参数-javaagent:C:/Users/manyh/.m2/repository/org/aspectj/aspectjweaver/1.9.7/aspectjweaver-1.9.7.jar完成,其中C:/Users/manyh/.m2/repository是本地maven仓库的地址
  3. JDK动态代理,JDK支持的动态代理方式
  4. cglib动态代理,spring提供的动态代理方式

主要介绍一下JDK动态代理CGlib动态代理,这两种方式也是Spring框架中使用的方式

JDK动态代理

特点:

  • 1、目标对象和代理对象间是兄弟关系,都实现同一个接口
  • 2、目标类可以修饰final关键字,不影响代理类的增强
public class JdkProxyDemo {

    interface Foo {
        void foo();
    }

    static class Target implements Foo {

        @Override
        public void foo() {
            System.out.println("target foo");
        }
    }

    // jdk 只能针对接口代理
    // cglib
    public static void main(String[] args) {
        // 目标对象
        Target target = new Target();

        // 用来加载在运行期间动态生成的字节码
        ClassLoader classLoader = JdkProxyDemo.class.getClassLoader();
        // 代理对象
        Foo proxy = (Foo) Proxy.newProxyInstance(classLoader, new Class[]{Foo.class}, (p, method, args1) -> {
            System.out.println("before...");
            // 通过反射调用method:方法.invoke(目标, 参数);
            Object result = method.invoke(target, args1);
            System.out.println("after...");
            // 让代理也返回目标方法执行的结果
            return result;
        });
        proxy.foo();
    }
}

cglib动态代理

特点:

  • 目标对象和代理对象间是父子关系,代理类继承目标类
  • 目标类加final关键字时会报错;目标类中的方法加了final关键字虽然不会报错,但不会被代理增强
  • 代理对象是通过方法重写完成的增强(静态方法不能被重写,同样也不能被增强)
public class CglibProxyDemo {

    static class Target {

        public void foo() {
            System.out.println("target foo");
        }
    }

    // cglib:代理是字类型,目标是父类型
    public static void main(String[] args) {
        Target target = new Target();

        Target proxy = (Target) Enhancer.create(Target.class, new MethodInterceptor() {
            /**
             *
             * @param o 代理类自己
             * @param method 当前执行的方法
             * @param args1 方法的执行参数
             * @param methodProxy 方法。。。。
             * @return
             * @throws Throwable
             */
            @Override
            public Object intercept(Object o, Method method, Object[] args1, MethodProxy methodProxy) throws Throwable {
                System.out.println("before...");
                // 通过反射调用method:方法.invoke(目标, 参数);
                // Object result = method.invoke(target, args1);
                // methodProxy 它可以避免反射调用
                Object result = methodProxy.invoke(target, args1);// 内部没有用反射,Spring 使用的是这种
                // invokeSuper方法的参数第一个参数只需要传入代理对象,不需要目标对象
                // Object result = methodProxy.invokeSuper(o, args1);// 内部没有用反射
                System.out.println("after...");
                return result;
            }
        });

        proxy.foo();
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值