• 代理学习


    1、静态代理

    测试类:

    package com.example.demo.proxy;
    
    public class StaticProxy implements UserDao {
    
        private UserDao userdao;
    
        public UserDao getUserdao() {
            return userdao;
        }
    
        public void setUserdao(UserDao userdao) {
            this.userdao = userdao;
        }
    
        @Override
        public void getUser() {
            System.out.println("代理类进入");
            userdao.getUser();
            System.out.println("代理类退出");
        }
    
    
        public static void main(String[] args) {
            StaticProxy sp = new StaticProxy();
            UserDao userDao = new UserDaoImpl();
            sp.setUserdao(userDao);
            sp.getUser();
    
        }
    }

    userdao:

    package com.example.demo.proxy;
    
    public interface UserDao {
    
        void getUser();
    }

    userdaoimpl:

    package com.example.demo.proxy;
    
    public class UserDaoImpl implements UserDao {
        @Override
        public void getUser() {
            System.out.println("userdao impl");
        }
    }

    运行测试类:

    代理类进入
    userdao impl
    代理类退出

    2、jdk动态代理
    测试类:

    package com.example.demo.proxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class DynamicProxy1 {
        //维护一个被代理的类
        private Object obj;
    
        public Object getObj() {
            return obj;
        }
    
        public void setObj(Object obj) {
            this.obj = obj;
        }
    
        public Object getInstance() {
            return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
                    obj.getClass().getInterfaces(),
                    new InvocationHandler() {
                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            System.out.println("进入proxy");
                            //invoke两个参数,obj原对象,args参数
                            method.invoke(obj, args);
                            System.out.println("退出proxy");
                            return null;
                        }
                    });
        }
    
        public static void main(String[] args) {
            DynamicProxy1 dp1 = new DynamicProxy1();
            dp1.setObj(new UserDaoImpl());
    
            UserDao instance = (UserDao) dp1.getInstance();
            instance.getUser();
        }
    }

    userdao和userdaoimpl同上

    运行测试类:

    进入proxy
    userdao impl
    退出proxy
    JDK动态代理局限性

    通过反射类Proxy和InvocationHandler回调接口实现的jdk动态代理,要求委托类必须实现一个接口,但事实上并不是所有类都有接口,对于没有实现接口的类,便无法使用该方方式实现动态代理。

    3、cglib动态代理

    静态代理和jdk动态代理模式都是要求目标对象实现一个接口,
    Cglib代理,也叫作子类代理,是基于asm框架,实现了无反射机制进行代理,利用空间来换取了时间,代理效率高于jdk ,它是在内存中构建一个子类对象从而实现对目标对象功能的扩展.
    它有如下特点:
    JDK的动态代理有一个限制,就是使用动态代理的对象必须实现一个或多个接口,如果想代理没有实现接口的类,就可以使用Cglib实现.
    Cglib是一个强大的高性能的代码生成包,它可以在运行期扩展java类与实现java接口.它广泛的被许多AOP的框架使用,例如Spring AOP和synaop,为他们提供方法的interception(拦截)
    Cglib包的底层是通过使用一个小而块的字节码处理框架ASM来转换字节码并生成新的类.不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉.
    注意
    需要引入cglib的jar文件,但是Spring的核心包中已经包括了Cglib功能,所以直接引入pring-core-3.2.5.jar即可.
    引入功能包后,就可以在内存中动态构建子类
    代理的类不能为final,否则报错
    目标对象的方法如果为final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法.
     
    测试类:
    package com.example.demo.proxy;
    
    import org.springframework.cglib.proxy.Enhancer;
    import org.springframework.cglib.proxy.MethodInterceptor;
    import org.springframework.cglib.proxy.MethodProxy;
    
    import java.lang.reflect.Method;
    
    /**
     * 实现methodInterceptor方法,并重写interceptor方法
     */
    public class CglibDynamicProxy implements MethodInterceptor {
        //维护一个被代理的对象
        private Object target;
    
        public Object getinstance() {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(target.getClass());
            //回调方法指定当前类即可(实现了methodInterceptor接口的类)
            enhancer.setCallback(this);
    
            return enhancer.create();
        }
    
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            System.out.println("cglib代理开始");
            Object invoke = method.invoke(target, objects);
            System.out.println("cglib代理结束");
            return invoke;
        }
    
    
        public static void main(String[] args) {
            CglibDynamicProxy cg = new CglibDynamicProxy();
            UserWithoutInterface u = new UserWithoutInterface();
            cg.setTarget(u);
            UserWithoutInterface instance = (UserWithoutInterface) cg.getinstance();
            instance.getuser();
    
        }
    
    
        public Object getTarget() {
            return target;
        }
    
        public void setTarget(Object target) {
            this.target = target;
        }
    }

    被代理对象UserwithoutInterface:

    package com.example.demo.proxy;
    
    public class UserWithoutInterface {
    
        public void getuser(){
            System.out.println("执行userwithoutInterface中的getuser方法");
        }
    }

    执行测试类结果:

    cglib代理开始
    执行userwithoutInterface中的getuser方法
    cglib代理结束

    参考:http://ifeve.com/java-reflection-11-dynamic-proxies/

  • 相关阅读:
    用DOS把一个文件夹下的所有文件名打印到txt文件里
    多线程时的CreateDispatch问题
    [转载]惟楚有才
    [转] 数学专业参考书整理推荐
    大整数处理类(cpp文件)
    [转]英文文献检索
    大整数处理类(头文件)
    国外遥感GIS期刊整理(转)
    [转载]Hibernate中No row with the given identifier exis
    在武汉,总有那么一个词~~~
  • 原文地址:https://www.cnblogs.com/nxzblogs/p/11014986.html
Copyright © 2020-2023  润新知