动态代理

jdk动态代理 & cglib动态代理

注意:这里为了方便代码展示,代理的方法都是匿名类部内进行的重写
jdk动态代理和cglib动态代理最大的区别是jdk必须要实现接口,否则无法代理,cglib则不需要实现接口,他会在目标类基础上创建一个子类进行增强
jdk和cglib在springaop应用,后续在了解了aop后会知道他的强大之处,很多全局的日志,全局异常处理,目标方法增强都会用到,大大减少我们的重复代码反射和动态代理的学习及其重要!

jdk动态代理demo

第一步: 新建一个接口

package com.proxy;
public interface JdkClass {
    String print();
}

第二步:写一个实现类继承上面的接口

package com.proxy;
public class jdkClassImpl implements JdkClass {
    @Override
    public String print() {
        System.out.println("我是一个jdk动态代理实现类....");
        return "OK";
    }
}

第三步:写jdk增强的实现代码

package com.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class JdkDynamicClass<T> {
	//把目标方法通过构造方法注入
    private T target;

    public JdkDynamicClass(T target) {
        this.target = target;

    }
    //这里是代理类的创建
    public T getProxy(){
        //这里是处理增强的类
        InvocationHandler invocationHandler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //proxy参数传递的即是代理实现类的实例
                System.out.println("jdk动态代理前置增强....");
                String result =(String) method.invoke(target, args);
                System.out.println(result);
                System.out.println("jdk动态代理后置增强....");
                return result;
            }
        };

        //执行增强并运行的方法!
        return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),invocationHandler);
    }
}

第四步: 测试

package com.proxy;
public class JDKRunTest {
    public static void main(String[] args) {
        //可以看到,目标类的add方法前后已经加入了自定义的切面逻辑,AOP拦截机制生效了。
        // 再看class com.sun.proxy.$Proxy0。这里进一步证明JDK动态代理的核心是InvocationHandler接口和Proxy类
        JdkDynamicClass<jdkClassImpl> jdkDynamicClass = new JdkDynamicClass<>(new jdkClassImpl());
        //这里的proxyInstance就是我们目标类的增强代理类
        JdkClass proxy = jdkDynamicClass.getProxy();
        proxy.print();
        System.out.println("======>"+ proxy.getClass());

    }
}

运行结果:
在这里插入图片描述

cglib动态代理demo

第一步: 写一个普通的class类

package com.proxy;

public class CglibClass {
    public void add(){
        System.out.println("cglib动态代理...");
    }
}

第二步: 测试,具体的cglib代码一起写在main方法中了,方便大家查看,也可以单独写一个类进行处理

package com.proxy;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class CglibTest {
    public static void main(String[] args) {
        //对目标类进行增强
        MethodInterceptor cglibProxy = new MethodInterceptor() {
            @Override              //参数1: 目标代理对象 参数2:目标类的method方法 , 参数3:目标类的参数列表  参数4:目标类的代理方法
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                System.out.println("cglib 前置增强...");
                //注意这里一定要用setSuperClass 它去找的是父类,编译看父类,执行走子类的实现! 这是java的基础
                //如果用invoke方法会出现无限循环,找不到父类,就会报栈溢出
                //proxy.invoke(0,objects) 执行的是原始方法!
                Object target = methodProxy.invokeSuper(o, objects);
                System.out.println("cglib 后置增强...");
                return target;
            }
        };
        //enhancer增强子,用于执行最后的增强!
        Enhancer enhancer = new Enhancer();
        //设置cglib的父类
        enhancer.setSuperclass(CglibClass.class);
        //增强的代理类
        enhancer.setCallback(cglibProxy);

        CglibClass cglibClass = (CglibClass)enhancer.create();
        //执行方法
        cglibClass.add();

        Class<? extends CglibClass> aClass = cglibClass.getClass();
        System.out.println("生成的cglib代理增强类: " + aClass);
        System.out.println("========分割线=========");
        //这一步打印cglib代理的父类,说明cglib是为目标类创建了一个子类,再对子类的增强... 所以他是不需要目标类实现一个接口的
        String name = aClass.getSuperclass().getName();
        System.out.println("cglib的父类:" + name);
    }
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值