Java动态代理 ----- jdk代理与cglib代理

1、jdk代理

针对接口进行代理,接口可以没有方法, InvocationHandler会拦截所有方法,不过好像意义不大....只能执行Object类的方法,执行结果有点奇怪...

package test;

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

public class TestJdkProxy {

    public static void main(String[] args) {

        //接口的实例对象,这里用的匿名对象
        Test test = new Test() {
        };

        //拦截类
        InvocationHandler invocationHandler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //proxy为实际创建的代理类, method为代理类执行的方法, args为方法调用对应的参数

                System.out.println("代理前");
                Object object = method.invoke(test, args);
                System.out.println("代理后");

                return object;
            }
        };

        Test proxy = (Test) Proxy.newProxyInstance(test.getClass().getClassLoader(),
                test.getClass().getInterfaces(), invocationHandler);

        System.out.println("-------------------------------");
        System.out.println(proxy.equals(proxy));  // ? 有点奇怪,  是false
        System.out.println("-------------------------------");
        System.out.println(Integer.toHexString(proxy.hashCode()));
        System.out.println("-------------------------------");
        System.out.println(proxy.toString());  // Object类的toString方法调用了一次hashCode方法,  toString方法和hashCode方法只拦截了一次?
    }

    public interface Test {

    }

}

输出为:

-------------------------------
代理前
代理后
false
-------------------------------
代理前
代理后
61bbe9ba
-------------------------------
代理前
代理后
test.TestJdkProxy$1@61bbe9ba

接口有方法情况:

package test;

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

public class TestJdkProxy {

    public static void main(String[] args) {

        //接口的实例对象,这里用的匿名对象
        Test test = new Test() {
            @Override
            public void test() {
                System.out.println("执行代理的接口方法");
            }
        };

        //拦截类
        InvocationHandler invocationHandler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //proxy为实际创建的代理类, method为代理类执行的方法, args为方法调用对应的参数

                System.out.println("代理前");
                Object object = method.invoke(test, args);
                System.out.println("代理后");

                return object;
            }
        };

        Test proxy = (Test) Proxy.newProxyInstance(test.getClass().getClassLoader(),
                test.getClass().getInterfaces(), invocationHandler);
        proxy.test();
    }

    public interface Test {
        void test();
    }

}

输出为

代理前
执行代理的接口方法
代理后

2、cglib代理

代理类不能为final 类,

maven引入jar包

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
        </dependency>
package test;

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 TestCglibProxy {

    public static void main(String[] args) throws Exception {

        MethodInterceptor handler = new MethodInterceptor() {
            @Override
            public Object intercept(Object proxy, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                //proxy为创建的代理类, 我的理解是对需要代理的类进行了继承(?), 所以需要代理的类不能为final类

                System.out.println("代理前");
                Object result = methodProxy.invokeSuper(proxy, objects);
                System.out.println("代理后");
                return result;
            }
        };

        Enhancer enhancer = new Enhancer();
        //设置需要代理的类,不能是final类
        enhancer.setSuperclass(Test.class);
        //设置方法拦截
        enhancer.setCallback(handler);
        //创建代理类,根据Test构造方法所需要的参数指定create参数, 如本例中Test类有String参数构造方法
        Test test = (Test) enhancer.create(new Class[]{String.class}, new Object[]{"Aa"});
        test.test();
        System.out.println("-------------------------------");
        test = (Test) enhancer.create();
        test.test();
        System.out.println("-------------------------------");
        //对代理类的方法都会进行拦截,  Object类的toString方法调用了一次hashCode方法,  toString方法和hashCode方法都进行了拦截
        System.out.println(test.toString());
        System.out.println("-------------------------------");
        System.out.println(test.equals(test));
    }

    public static class Test {

        private String str;

        public void test() {
            System.out.println("test : " + str);
        }

        public Test() {

        }

        public Test(String string) {
            str = string;
        }

    }

}

输出为

代理前
test : Aa
代理后
-------------------------------
代理前
test : null
代理后
-------------------------------
代理前
代理前
代理后
代理后
test.TestCglibProxy$Test$$EnhancerByCGLIB$$d7a97ec4@7506e922
-------------------------------
代理前
代理后
true

 

posted @ 2019-11-20 14:33  笪笠  阅读(153)  评论(0编辑  收藏  举报