Java学习路线(25)——动态代理

一、概述

(一)代理的概念: 某些场景下对象会找一个代理对象辅助完成工作。
(二)代理的作用: 为了防止外部直接调用功能,需要中间对象代理实际对象完成功能调用并可执行额外功能。
(三)代理对象 java,lang.reflect.Proxy API

方法 说明
static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h) 指定类加载器、代理类接口列表、处理程序获取代理类

(三)代理的工作原理:
在这里插入图片描述


二、初步使用

/*
* 以歌手与经纪人关系做解释
*/

public class ProxyDemo {
    
    
    public static void main(String[] args) {
    
    
        //1、创建实际对象(歌手)
        Singer singer = new Singer("歌手");
        singer.work();

        //2、创建代理
        work proxy = SingerProxy.getProxy(singer);
        proxy.sing();
        proxy.dance();
    }
}

interface work{
    
    
    void dance();
    void sing();
}

class Singer implements work{
    
    
    private String name;

    public Singer() {
    
    
    }

    public Singer(String name) {
    
    
        this.name = name;
    }

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    public void sing(){
    
    
        System.out.println(this.name + "正在唱歌");
    }

    public void dance(){
    
    
        System.out.println(this.name + "正在跳舞");
    }

    public void work(){
    
    
        sing();
        dance();
    }

    @Override
    public String toString() {
    
    
        return "Singer{" +
                "name='" + name + '\'' +
                '}';
    }
}

class SingerProxy{
    
    
    public static work getProxy(Singer singer){
    
    
        return (work) Proxy.newProxyInstance(
                //类加载器
                singer.getClass().getClassLoader(),
                //对象接口实现列表
                singer.getClass().getInterfaces(),
                //核心程序
                new InvocationHandler() {
    
    
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    
                        System.out.println("收款");
                        Object res = method.invoke(singer,args);
                        System.out.println("给周边");
                        return res;
                    }
                }
        );
    }
}

/*打印输出*/
歌手正在唱歌
歌手正在跳舞
收款
歌手正在唱歌
给周边
收款
歌手正在跳舞
给周边

三、应用案例

案例:性能分析

需求:将每个功能耗时统计出来。
public class ProxyTest {
    
    
    public static void main(String[] args) {
    
    
        UserLogin userLogin = UserLoginProxy.userLogin(new UserLoginImpl());
        System.out.println(userLogin.login("admin", "123456"));
        userLogin.select();
        userLogin.delete();
    }
}

interface UserLogin{
    
    
    String login(String uname, String password);
    void delete();
    void select();
}

class UserLoginImpl implements UserLogin{
    
    

    @Override
    public String login(String uname, String password) {
    
    
        try {
    
    
            Thread.sleep(1000);
        } catch (InterruptedException e) {
    
    
            throw new RuntimeException(e);
        }
        return uname.equals("admin") && password.equals("123456") ? "登录成功":"登录失败";
    }

    @Override
    public void delete() {
    
    
        try {
    
    
            Thread.sleep(2500);
        } catch (InterruptedException e) {
    
    
            throw new RuntimeException(e);
        }
    }

    @Override
    public void select() {
    
    
        try {
    
    
            Thread.sleep(2500);
        } catch (InterruptedException e) {
    
    
            throw new RuntimeException(e);
        }
    }
}

class UserLoginProxy{
    
    
    public static UserLogin userLogin(UserLogin impl){
    
    
        return (UserLogin) Proxy.newProxyInstance(impl.getClass().getClassLoader(), impl.getClass().getInterfaces(), new InvocationHandler() {
    
    
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    
                long start = System.currentTimeMillis();
                Object o = method.invoke(impl,args);
                long end = System.currentTimeMillis();
                System.out.println("=========="+method.getName()+"()方法,时间:"+(end - start)+" s ==========");
                return o;
            }
        });
    }
}

/*打印输出*/
==========login()方法,时间:1005 s ==========
登录成功
==========select()方法,时间:2503 s ==========
==========delete()方法,时间:2506 s ==========

动态代理的优点

  • 在不改变方法源码的情况下,增强方法功能,提高代码复用
  • 简化编程工作、提高开发效率,同时提高软件系统扩展性
  • 可以为实际对象的所有方法做代理
  • 灵活,支持任意接口类型的实现类对象做代理,或直接为接口本身做代理

猜你喜欢

转载自blog.csdn.net/Zain_horse/article/details/131097510