JAVA-动态代理篇


public class JavaSist02 {
    /**
     *  JDK 动态代理 与 Cglib 动态代理
     *  1: JDK 动态代理是利用 java 反射机制与JDK自身 class 生成 。 在调用本身方法前调用invokeHandler来处理
     *  2: CGlib 动态代理则是利用 asm 开源包。对代理的类的 class 文件加载进来 。通过修改其字节码生成子类来处理
     *
     *  如果目标对象实现了接口,默认使用 JDK代理 来实现 AOP
     *  如果目标对象实现了接口,可强制使用CGlib接口来实现AOP
     *
     *  如何强制使用CGLIB实现AOP?
     *  (1)添加CGLIB库,SPRING_HOME/cglib/*.jar
     *  (2)在spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>
     *
     *  JDK 动态代理与 CGlib 的区别
     *  (1)JDK动态代理只能对实现了接口的类生成代理,而不能针对类
     *  (2)CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法
     */


    public static void main(String[] args) throws Exception {
        // 利用 sist 实现动态代理
        crateProxy(TestService.class, (methodName, args13) -> {
            System.out.println("hello:" + args13[0]) ;
            return null;
        }).sayHello("上卿");

        crateProxy(TestService.class, (methodName, args12) -> {
            System.out.println("hello:" + args12[0] + "年龄" + args12[1]) ;
            return null;
        }).sayHello("上卿", 18);


        String sayHello = crateProxy(TestService.class, (methodName, args1) -> String.format("姓名:%s,性别:%s",args1)).sayHello("上卿", "男");
        System.out.println(sayHello);

    }

    static int count = 0;
    public static <T> T crateProxy(Class<T> interfaceClazz , InvocationHeadler headler) throws Exception{
        ClassPool pool = new ClassPool();

        pool.appendSystemPath();

        // 防止类名重复
        CtClass proxy = pool.makeClass("proxy" + count++);
        proxy.addInterface(pool.get(interfaceClazz.getName()));
        // 添加属性

        CtField make = CtField.make("public com.shangqing.api.proxy.JavaSist02.InvocationHeadler headler=null;", proxy);
        proxy.addField(make);

        String result  = "return ($r)this.headler.invoke(\"$s\",$args);";

        String voidResult = "this.headler.invoke(\"$s\",$args);";

        for (Method method : interfaceClazz.getMethods()) {
            // 返回值类型,方法名称,参数,异常,实现类
            CtClass returnType = pool.get(method.getReturnType().getName());
            String methodName = method.getName();
            CtClass[] parameters = toCtClass(pool, method.getParameterTypes());
            CtClass[] errors = toCtClass(pool, method.getExceptionTypes());
            String srcImpl;
            if (method.getReturnType().equals(Void.class)) {
                srcImpl = voidResult;
            } else {
                srcImpl = result;
            }

            CtMethod ctMethod = CtNewMethod.make(returnType, methodName, parameters, errors, srcImpl, proxy);
            proxy.addMethod(ctMethod);
        }
        // toClass 同时会将 类加载到 classloader 中
        Class toClass = pool.toClass(proxy);
        T t = (T) toClass.newInstance();
        toClass.getField("headler").set(t,headler);

        return t;
    }

    private static CtClass[] toCtClass(ClassPool pool , Class[] classes){
        return Arrays.stream(classes).map(c -> {
            try {
                return pool.get(c.getName());
            } catch (NotFoundException e) {
                throw new RuntimeException(e);
            }
        }).toArray(CtClass[]::new);
    }

    public interface InvocationHeadler{
        Object invoke(String methodName , Object[] args);

    }


    public interface TestService{
        void sayHello(String name);

        void sayHello(String name,int age);

        String sayHello(String name,String sex);
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值