Java动态代理学习

Java动态代理学习

前言

我们在以前需要对代码进行输出 或者 一些代码增加的时候会这样 直接侵入修改

image-20230330213302849
image-20230330213636718

自己写点题目都还好。但是在一个项目中 如果直接这样修改就很容易出现问题。

在我们通常中常会用到动态代理

动态代理

我们这个案例基于 一个 star 他会做出 sing 或者dance的操作

BigStar部分用于 需要实现的业务逻辑功能

Star 部分作为接口

ProxyUtil 部分用为于业务对象做一个代理对象。

package study1;

public class BigStar implements Star{
    private String name;

    public BigStar() {
    }

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

    //sing dance
    @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 study1;

public interface Star {

    public abstract String sing(String name);

     public abstract void dance();
}
package study1;

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

public class ProxyUtil {
   /*
   *方法的作用:
   *
   *     给一个明星的对象,创建一个代理。
   *
   * 形参:
   *
   *    被代理的明星对象
   *
   * 返回值:
   *
   *    给明星创建的代理
   *
   * 需求:
   *
   *外面的人想要大明星唱歌:
   *1. 获取代理的对象
   *
   *   代理对象 = ProxyUtil.createProxy(大明星的对象);
   *
   * 2.再调用代理的唱歌方法
   *   代理对象.唱歌的方法("歌曲名称")
   *
   */
    public static Star createProxy(BigStar bigStar){

        Star star = (Star) Proxy.newProxyInstance(
                ProxyUtil.class.getClassLoader(),  //类加载器
                new Class[]{Star.class},      //指定接口 用于指定代理长什么样 也就是有哪些方法
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                        /*
                        *参数一:代理对象
                        *参数二:要运行时调用的方法
                        * 参数三:调用sing方法时,传递的实参。
                        *
                         */

                        if ("sing".equals(method.getName())){
                            System.out.println("准备话筒,收钱");
                        } else if ("dance".equals(method.getName())) {
                            System.out.println("准备场地,收钱");
                        }
                        //去找大明星开始唱歌或者跳舞
                        //代码的表现形式:调用大明星唱歌或者跳舞的方法
                        return method.invoke(bigStar,args);

                    }
                }
        );

        return star;
    }
}

package study1;

public class Test {
    public static void main(String[] args) {

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

        //调用唱歌的方法
        String result = proxy.sing("sing");
        System.out.println(result);

        //调用跳舞的方法
        proxy.dance();

    }
}

这样当如果还需要增加新的业务的时候就只需要增加正常的业务逻辑代码就可以了。而不需要去修改其他地方的代码。