• 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
  • 相关阅读:
    太有才了!街头创意涂鸦手绘图片欣赏【上篇】
    设计前沿:25款精妙的 iOS 应用程序图标
    Web 前端开发精华文章集锦(jQuery、HTML5、CSS3)【系列十八】
    神奇的世界!那些使用食物创造出来的景观【组图】
    Screenfly – 各种设备的屏幕和分辨率下快速测试网站
    经典网页设计:30个新鲜出炉的扁平化网站设计《下篇》
    40款很奇异的名片设计,吸引你的眼球《下篇》
    推荐25款实用的 HTML5 前端框架和开发工具【下篇】
    CSS3 Animation Cheat Sheet:实用的 CSS3 动画库
    今日推荐:12个获取手机应用程序设计灵感的网站
  • 原文地址:https://www.cnblogs.com/wushengwuxi/p/11897618.html
Copyright © 2020-2023  润新知