Java动态代理机制,创建代理对象的方法(InvocationHandler,Proxy)

2024-01-08 23:16:48

1.什么是动态代理

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

在Java中,动态代理是一种机制,允许在运行时创建一个代理对象来代替原始对象,并可以在代理对象的方法执行前后追加额外的逻辑。动态代理是通过Java的反射机制实现的。
动态代理常用于在不修改原始类的情况下,增加额外的功能或在方法执行前后进行一些操作,比如日志记录、性能统计、事务管理等。

动态代理主要涉及两个关键接口:InvocationHandler和Proxy
InvocationHandler负责实现代理对象的方法逻辑,而Proxy则用于创建代理对象。
使用动态代理,需要创建一个实现了InvocationHandler接口的类来处理代理对象的方法调用。
在InvocationHandler接口的invoke方法中,可以对原始对象的方法进行增强
然后,通过Proxy类的静态方法newProxyInstance来创建代理对象,同时指定要代理的接口类型和InvocationHandler对象。
最后,通过代理对象来调用方法,实际上会调用InvocationHandler的invoke方法
动态代理的优点是可以在不修改原始类的情况下,增加或改变其行为
它具有较高的灵活性和可扩展性,可以应用于各种场景,如AOP编程、远程方法调用等。

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

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

编写一个明星行为接口Star:

public interface Star {
    //想要被代理的方法写在接口当中
    //唱歌
    public abstract String sing(String name);

    //跳舞
    public abstract void dance();
}

创建一个BigStar类实现Star接口,重写方法:

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 + "}";
    }
}

创建一个代理类ProxyUtil,利用反射用于增强明星类Star的方法(行为):

/**
 * 创建一个代理
 */
public class ProxyUtil {
    /**
     * 给一个明星的对象,创建一个代理
     *
     * @param bigStar 被代理的明星对象
     * @return 给明星创建的代理
     */
    public static Star createProxy(BigStar bigStar) {
        Star star = (Star) Proxy.newProxyInstance(
                ProxyUtil.class.getClassLoader(),//用于指定类加载器,去加载生成的代理类
                new Class[]{Star.class},//指定接口,表明接口内部的方法
                new InvocationHandler() {//指定代理对象的增强功能
                    /**
                     *
                     * @param proxy the proxy instance that the method was invoked on
                     *
                     * @param method the {@code Method} instance corresponding to
                     * the interface method invoked on the proxy instance.  The declaring
                     * class of the {@code Method} object will be the interface that
                     * the method was declared in, which may be a superinterface of the
                     * proxy interface that the proxy class inherits the method through.
                     *
                     * @param args an array of objects containing the values of the
                     * arguments passed in the method invocation on the proxy instance,
                     * or {@code null} if interface method takes no arguments.
                     * Arguments of primitive types are wrapped in instances of the
                     * appropriate primitive wrapper class, such as
                     * {@code java.lang.Integer} or {@code java.lang.Boolean}.
                     *
                     * @return
                     * @throws Throwable
                     */
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        if ("sing".equals(method.getName())) {
                            System.out.println("准备话筒,收钱,开始唱歌");
                        } else if ("dance".equals(method.getName())) {
                            System.out.println("准备场地,收钱,开始跳舞");
                        }
                        //调用实现类的方法
                        return method.invoke(bigStar, args);
                    }
                }
        );
        return star;
    }    
}

主函数:测试明星的代理人的方法增强效果

public class Test {
    public static void main(String[] args) {
        //获取代理的方法
        BigStar bigStar = new BigStar("鸡哥");
        Star proxy = ProxyUtil.createProxy(bigStar);
        //调用唱歌的方法
        String result = proxy.sing("只因你太美");
        System.out.println(result);
        /**
         * 准备话筒,收钱,开始唱歌
         * 鸡哥正在唱只因你太美
         * 谢谢
         */
        //调用跳舞的方法
        proxy.dance();
        /**
         * 准备场地,收钱,开始跳舞
         * 鸡哥正在跳舞
         */
    }
}

文章来源:https://blog.csdn.net/qq_61888137/article/details/135466438
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。