zoukankan      html  css  js  c++  java
  • 代理代码实现

    jdk动态代理

    1、有个Person接口

    package com.xiangwen.day5.jdk;
    
    public interface Person {
        public void say(String str);
        public void listen(String str);
    }

    2、有个PersonImpl接口实现类

    package com.xiangwen.day5.jdk;
    
    
    public class PersonImpl implements Person {
        @Override
        public void say(String str) {
            System.out.println(str);
        }
    
        @Override
        public void listen(String str) {
            System.out.println(str);
        }
    }

    3、创建接口的代理类PersonProxy

    package com.xiangwen.day5.jdk;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    public class PersonProx implements InvocationHandler {
        private Person person;
    
        public PersonProx(Person person) {
            this.person = person;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            Object o=null;
            if("say".equals(method.getName())){
                System.out.println("111111111befre---------------");
                 o=method.invoke(person,args);
                System.out.println("111111111end-----------------");
            }else if("listen".equals(method.getName())){
                System.out.println("222222222befre---------------");
                o=method.invoke(person,args);
                System.out.println("222222222end-----------------");
            }
            return o;
        }
    }

    4测试

    package com.xiangwen.day5.jdk;
    
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Proxy;
    
    public class Test {
        public static void main(String[] args) {
            Person person=new PersonImpl();
            InvocationHandler personProx=new PersonProx(person);
            Person p= (Person) Proxy.newProxyInstance(personProx.getClass().getClassLoader(),person.getClass().getInterfaces(),personProx);
            p.say("hello");
            System.out.println();
            p.listen("祝你平安!");
        }
    }

    结果截图:

    cglib动态代理

    maven依赖:

      <dependency>
                <groupId>cglib</groupId>
                <artifactId>cglib</artifactId>
                <version>3.2.11</version>
            </dependency>
            <dependency>
                <groupId>org.objectweb.asm</groupId>
                <artifactId>com.springsource.org.objectweb.asm</artifactId>
                <version>3.1.0</version>
            </dependency>

    1.有一个类PerosonImpl

    package com.xiangwen.day5.cglib;
    
    import com.xiangwen.day5.jdk.Person;
    
    public class PersonImpl  {
        public void say(String str) {
            System.out.println("说:"+str);
        }
        public void listen(String str) {
            System.out.println("听:"+str);
        }
    }
    

    2、建一个代理类为方法1处理

    package com.xiangwen.day5.cglib;
    
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    import java.lang.reflect.Method;
    
    public class PersonProx implements MethodInterceptor {
        @Override
        public Object intercept(Object object, Method method, Object[] objects, MethodProxy proxy) throws Throwable {
            System.out.println("Before Method Invoke");
            proxy.invokeSuper(object, objects);
            System.out.println("After Method Invoke");
            return object;
        }
    }

    3、建第二个代理类为方法2处理

    package com.xiangwen.day5.cglib;
    
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    import java.lang.reflect.Method;
    
    public class PersonProx2 implements MethodInterceptor {
        @Override
        public Object intercept(Object object, Method method, Object[] objects, MethodProxy proxy) throws Throwable {
            System.out.println("PersonProx2====Before Method Invoke");
            proxy.invokeSuper(object, objects);
            System.out.println("PersonProx2====After Method Invoke");
            return object;
        }
    }

    4、建一个MyFilter方法与代理类的顺序

    package com.xiangwen.day5.cglib;

    import net.sf.cglib.proxy.CallbackFilter;

    import java.lang.reflect.Method;

    public class MyFilter implements CallbackFilter {
    @Override
    public int accept(Method method) {
    if("say".equals(method.getName())){
    return 0;
    }else if("listen".equals(method.getName())){
    return 1;
    }
    return 1;//下标不能超过new Callback[]数组的下表,否则会报错
    }
    }

    5、测试

    @org.junit.Test
    public void test2(){
        PersonProx personProxy = new PersonProx();
        PersonProx2 personProxy2 = new PersonProx2();
        MyFilter filter=new MyFilter();
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(PersonImpl.class);
        enhancer.setCallbacks(new Callback[]{personProxy,personProxy2});
        enhancer.setCallbackFilter(filter);
        PersonImpl person = (PersonImpl)enhancer.create();
        person.say("说你爱我");
        System.out.println();
        person.listen("听雨");
    }

    6、结果截图

     如果不单独指定代理,所有方法都用personProxy代理

       public static void main(String[] args) {
            PersonProx personProxy = new PersonProx();
    
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(PersonImpl.class);
            enhancer.setCallback(personProxy);
            PersonImpl person = (PersonImpl)enhancer.create();
            person.say("说你爱我");
            person.listen("听雨");
        }

    区别:

    jdk:利用拦截器(拦截器必须实现InvocationHanlder)加上反射机制生成一个实现代理接口的匿名类,
    在调用具体方法前调用InvokeHandler来处理。

    JDK动态代理只能对实现了接口的类生成代理,而不能针对类。

    cglib:利用ASM开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

    CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,
    并覆盖其中方法实现增强,但是因为采用的是继承,所以该类或方法最好不要声明成final,
    对于final类或方法,是无法继承的。

    什么情况使用:

    1)如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP。

    2)如果目标对象实现了接口,可以强制使用CGLIB实现AOP。

    3)如果目标对象没有实现了接口,必须采用CGLIB库,Spring会自动在JDK动态代理和CGLIB之间转换。

    sping如何选择jdk和cglib
    如果bean实现接口,默认使用jdk动态代理
    如果bean没有实现接口,默认使用cglib动态代理
    在Spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>强制使用cglib
     
    哪个更快

    1)使用CGLib实现动态代理,CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类,在jdk6之前比使用Java反射效率要高。唯一需要注意的是,CGLib不能对声明为final的方法进行代理,因为CGLib原理是动态生成被代理类的子类。

    2)在jdk6、jdk7、jdk8逐步对JDK动态代理优化之后,在调用次数较少的情况下,JDK代理效率高于CGLIB代理效率,只有当进行大量调用的时候,jdk6和jdk7比CGLIB代理效率低一点,但是到jdk8的时候,jdk代理效率高于CGLIB代理,总之,每一次jdk版本升级,jdk代理效率都得到提升,而CGLIB代理效率确有点跟不上步伐。



  • 相关阅读:
    第二册二十一课
    第二册第二十课
    第二册第十九课
    第二册第十八课
    あなたがいるから (因为有你)
    flash 概要分析器
    this与回调函数
    cpp可变参笔记
    struct详解
    函数传递小结
  • 原文地址:https://www.cnblogs.com/wenwenzuiniucha/p/14900483.html
Copyright © 2011-2022 走看看