Java代理

什么是动态代理?

特点:无侵入式地给代码增加额外的功能

程序为什么需要代理?代理长什么样?

  1. 对象如果嫌身上干的事太多的话,可以通过代理来转移部分职责
  2. 对象有什么方法想被代理,代理就一定要有对应的方法

如何为 Java 对象创建一个代理对象?

  • java.lang.reflect.Proxy 类:提供了为对象产生代理对象的方法:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
// 参数一:用于指定用哪个类加载器,去加载生成的代理类
// 参数二:指定接口,这些接口用于指定生成的代理长什么,也就是有哪些方法
// 参数三:用来指定生成的代理对象要干什么事情
package com.faxont.dynamicproxy1;

public class BigStar implements Star{
    private String name;

    public BigStar() {
    }

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

    // 唱歌
    @Override
    public String sing(String name){
        System.out.println(this.name + "正在唱:" + name);
        return "谢谢";
    }

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

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    public String toString() {
        return "BigStar{name = " + name + "}";
    }
}
package com.faxont.dynamicproxy1;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 类的作用:
 *      创建一个代理
 */
public class ProxyUtil {

    /**
     * 方法的作用:
     *          给一个明星对象创建一个代理
     * @param bigStar
     *
     * 形参:
     *      被代理的明星对象
     *
     * 返回值:
     *      给明星创建的代理
     *
     * 需求:
     *      外面的人想要大明星唱一首歌
     *          1. 获取代理对象
     *              代理的对象 = ProxyUtil.createProxy(大明星的对象);
     *          2. 再调用代理的唱歌方法
     *              代理对象.唱歌的方法();
     */
    public static Star createProxy(BigStar bigStar){
        /*
            java.lang.reflect.Proxy 类:提供了为对象产生代理对象的方法:

            public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
            参数一:用于指定用哪个类加载器,去加载生成的代理类
            参数二:指定接口,这些接口用于指定生成的代理长什么,也就是有哪些方法
            参数三:用来指定生成的代理对象要干什么事情
         */

        Star star = (Star) Proxy.newProxyInstance(
                ProxyUtil.class.getClassLoader(),// 参数一:用于指定用哪个类加载器,去加载生成的代理类
                new Class[]{Star.class},// 参数二:指定接口,这些接口用于指定生成的代理长什么,也就是有哪些方法
                new InvocationHandler(){
                    /**
                     * 参数一:代理的对象
                     * 参数二:要运行的方法 sing()
                     * 参数三:调用 sing() 方法时,传递的实参
                     * @param proxy
                     * @param method
                     * @param args
                     * @return
                     * @throws Throwable
                     */
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        if(method.getName().equals("sing")){
                            System.out.println("收钱,准备话筒");
                        }else if(method.getName().equals("dance")){
                            System.out.println("收钱,准备场地");
                        }
                        // 去找大明星开始唱歌或者跳舞
                        // 代码的表现形式:调用大明星类名唱歌或者跳舞的方法
                        return method.invoke(bigStar, args);
                    }
                }// 参数三:用来指定生成的代理对象要干什么事情
        );
        return star;
    }
}
package com.faxont.dynamicproxy1;

public interface Star {
    // 唱歌
    public abstract String sing(String name);

    // 跳舞
    public abstract void dance();
}
package com.faxont.dynamicproxy1;

public class Test {
    public static void main(String[] args) {
        /*
            需求:
            外面的人想要大明星唱一首歌
                1. 获取代理对象
                    代理的对象 = ProxyUtil.createProxy(大明星的对象);
                2. 再调用代理的唱歌方法
                    代理对象.唱歌的方法();
         */

        // 1. 获取代理对象
        BigStar bigStar = new BigStar("tokyomanaka");
        Star proxy = ProxyUtil.createProxy(bigStar);

        // 2. 调用唱歌的方法
        String result = proxy.sing("ブレインロット");
        System.out.println(result);

        // 3. 调用跳舞的方法
        proxy.dance();
    }
}
posted @ 2026-05-16 21:45  弋湖  阅读(16)  评论(0)    收藏  举报