美文网首页JAVA
Java中的三种代理模式

Java中的三种代理模式

作者: 哪吒小子 | 来源:发表于2018-12-05 17:02 被阅读13次

    第一种:静态代理

    程序实现

    代码实现

    1.设计接口

    public interface IUserDao {
        void save();
    }
    

    2.实现接口

    public class UserDao implements IUserDao {
        @Override
        public void save() {
            System.out.println("----已经保存数据!----");
        }
    }
    

    3.代理类

    必须实现接口

    public class UserDaoProxy implements IUserDao {
        //接收保存目标对象
        private IUserDao target;
        public UserDaoProxy(IUserDao target){
            this.target=target;
        }
        @Override
        public void save() {
            System.out.println("开始事务...");
            target.save();//执行目标对象的方法
            System.out.println("提交事务...");
        }
    }
    

    4.测试类

    public class App {
        public static void main(String[] args) {
            //目标对象
            UserDao target = new UserDao();
            //代理对象,把目标对象传给代理对象,建立代理关系
            UserDaoProxy proxy = new UserDaoProxy(target);
            proxy.save();//执行的是代理的方法
        }
    }
    

    第二种:JDK动态代理

    代码实现

    1.设计接口

    public interface IUserDao {
        void save();
    }
    

    2.实现接口

    public class UserDao implements IUserDao {
        @Override
        public void save() {
            System.out.println("----已经保存数据!----");
        }
    }
    

    3.代理类

    不需要实现接口

    public class ProxyFactory {
        //维护一个目标对象
        private Object target;
        public ProxyFactory(Object target){
            this.target=target;
        }
    
        //这是Java8语法
        public Object getProxyInstanceLambda(){
            return Proxy.newProxyInstance(
                    target.getClass().getClassLoader(),
                    target.getClass().getInterfaces(),
                    (proxy,method,args) -> {
                        System.out.println("开始事务2");
                        //执行目标对象方法
                        Object returnValue = method.invoke(target, args);
                        System.out.println("提交事务2");
                        return returnValue;
                    });
        }
        
        //传统语法
        public Object getProxyInstance(){
            return Proxy.newProxyInstance(
                    target.getClass().getClassLoader(),
                    target.getClass().getInterfaces(),
                    new InvocationHandler() {
                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            System.out.println("开始事务2");
                            //执行目标对象方法
                            Object returnValue = method.invoke(target, args);
                            System.out.println("提交事务2");
                            return returnValue;
                        }
                    });
        }
    }
    

    4.测试类

    public class App {
        public static void main(String[] args) {
            // 目标对象
            IUserDao target = new UserDao();
            // 【原始的类型 class UserDao】
            System.out.println(target.getClass());
    
            // 给目标对象,创建代理对象
            IUserDao proxy = (IUserDao) new ProxyFactory(target).getProxyInstanceLambda();
            // class $Proxy0   内存中动态生成的代理对象
            System.out.println(proxy.getClass());
    
            // 执行方法   【代理对象】
            proxy.save();
        }
    }
    

    第三种:Cglib代理

    代码实现

    1.目标对象类

    public class UserDao {
        public void save() {
            System.out.println("----已经保存数据!----");
        }
    }
    

    2.Cglib代理工厂

    public class ProxyFactory implements MethodInterceptor {
        //维护目标对象
        private Object target;
    
        public ProxyFactory(Object target) {
            this.target = target;
        }
    
        //给目标对象创建一个代理对象
        public Object getProxyInstance(){
            //1.工具类
            Enhancer en = new Enhancer();
            //2.设置父类
            en.setSuperclass(target.getClass());
            //3.设置回调函数
            en.setCallback(this);
            //4.创建子类(代理对象)
            return en.create();
    
        }
    
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            System.out.println("开始事务...");
            //执行目标对象的方法
            Object returnValue = method.invoke(target, objects);
            System.out.println("提交事务...");
            return returnValue;
        }
    }
    

    3.测试类

    public class App {
    
        public static void main(String[] args) {
            //目标对象
            UserDao target = new UserDao();
            //代理对象
            UserDao proxy = (UserDao)new ProxyFactory(target).getProxyInstance();
            //执行代理对象的方法
            proxy.save();
        }
    }
    

    三者的区别

    1.静态代理

    目标对象要实现接口,而且代理对象需要实现接口。
    这样的代理类只能代理特定接口的对象,灵活度不够。

    2.JDK动态代理

    代理对象不需要实现接口,但是目标对象一定要实现接口,否则不能用动态代理

    3.CGLib动态代理

    代理对象不需要实现接口,目标对象也可以是单纯的一个对象。


    在Spring的AOP编程中:
    如果加入容器的目标对象有实现接口,用JDK代理.
    如果目标对象没有实现接口,用Cglib代理.

    参考文献

    详解 Java 中的三种代理模式:https://mp.weixin.qq.com/s/nBmbNP2mR7ei-lDsuOxjWg

    你真的完全了解Java动态代理吗?看这篇就够了:https://mp.weixin.qq.com/s/P-nrfyyWfRUurKgF4dnugA

    相关文章

      网友评论

        本文标题:Java中的三种代理模式

        本文链接:https://www.haomeiwen.com/subject/nkywcqtx.html