Java动态代理

一. 什么是动态代理

Java动态代理_第1张图片

  • 假设Student里面有一个吃饭的eat方法,那么现在我要给这个方法去增加其他的功能,比如说吃饭之前,要去拿筷子,要去盛饭,按照以前所学,我们只能把这两段代码都写在eat方法当中,那此时直接去修改代码,是叫做侵入式修改。

Java动态代理_第2张图片

  • 在以后在一个成熟的项目当中,我们一般很少会这么去干。
  • 那么问题来了,我现在又不能去修改原有的代码,又要去增加额外的功能,那这个时候我该怎么办呢?
  • 此时我们就得去找一个代理,什么是代理,说白了就是中介公司。
  • 代理会帮你先去做拿筷子和盛饭这两个准备工作,等真正的吃饭了再去调用Student里面的方法去吃饭,这个呢其实就是动态代理。

1.为什么需要代理呢?

  • 代理可以无侵入式的给对象增强其他的功能。
  • 当调用者去调用对象中的方法的时候,其实呢不是直接通过对象去调用,而是先去调用代理中的方法,代理会做一些准备工作,然后呢再由代理去调用对象中的方法,是有这样的一个过程
  • Java动态代理_第3张图片

Java动态代理_第4张图片

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

Java动态代理_第5张图片

Java动态代理_第6张图片

程序为什么需要代理?

  •  说白了就是因为如果对象任务自己身上干的事情太多了,就可以通过代理转义部分的职责。

那么中介派出的这个代理它是长什么样子的呢?

  • 代理里面就是对象要被代理的所有的方法
  • 在代码当中代理长什么样子,说白了就是代理的里面可以写什么样的方法。
  • 代理长什么样子,其实是跟对象差不多的。
  • 对象要有什么方法想要被代理,那么代理呢也要有对应的方法,只不过方法里面干的事情是不太一样的,代理它会先把准备工作做完,然后再去调用对象中的方法。
  • 代理是通过接口去知道对象想要代理的方法,在这个接口里面所有的方法就是我们想要代理的方法。
  • 左边的代理和右边的对象都要去实现中间的这个接口才是可以的!

Java动态代理_第7张图片

  1.  为什么需要代理?
  • 代理可以无侵入式的给对象增强其他的功能。
  1. 代理长什么样?
  • 代理里面就是对象要被代理的所有的方法。
  1. Java通过什么来保证代理的样子?
  • Java通过接口保证代理的样子,对象和代理需要实现同一个接口,接口中就是被代理的所有的方法。

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

Java动态代理_第8张图片

 

package com.gch.d10_dynamic_proxy;

/**
   定义大明星类:模拟对象
 */
public class BigStar implements Star{
    private String name;


    public BigStar() {
    }

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

    /**
     * 唱歌
     * @param name:歌曲的名字
     * @return:"谢谢"
     */
    @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.gch.d10_dynamic_proxy;

/**
   接口:接口当中定义的是对象所有想要被代理的方法(抽象方法)
   我们可以把所有想要被代理的方法定义在接口当中
 */
public interface Star {
    /**
     * 唱歌
     * @param name:歌曲名
     */
    public abstract String sing(String name);

    /**
       跳舞
     */
    public abstract void dance();
}
package com.gch.d10_dynamic_proxy;

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

/**
 * 代理类
 * 类的作用:创建一个代理
 */
public class ProxyUtil {
    
    /**
     * 方法的作用:给一个对象,去创建一个代理对象
     * 方法的返回值类型直接写接口的类型,因为我们的代理也是要去实现接口的
     * @param bigstar:形参:被代理的明星对象
     * @return  返回值:给明星创建的代理对象
     */
    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} // 参数二:指定接口,这个就表示我们生成的这个代理,也就是中介,它可以代理Star这个接口里面所有的方法
                , new InvocationHandler() { // 参数三:用来指定生成的代理对象要干什么事情
                    @Override
                    /**
                     * 用来指定生成的代理对象要干什么事情 invoke:调用
                     * 参数一:表示代理的对象,重点看参数二和参数三
                     * 参数二:要运行的方法  sing,dance...
                     * 参数三:调用sing方法时,传递的实参
                     */
                    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;
    }
}
package com.gch.d10_dynamic_proxy;

/**
 需求:
     外面的人想要大明星唱一首歌
     1.获取代理对象
         代理对象 = ProxyUtil.createProxy(大明星的对象);
     2.再调用代理的唱歌方法
        代理对象.唱歌的方法("只因你太美");
 */
public class Test {
    public static void main(String[] args) {
        // 1.创建对象
        BigStar bigStar = new BigStar("鸡哥");

        // 2.获取代理的对象  proxy:代理
        Star proxy = ProxyUtil.createProxy(bigStar);

        // 3.调用唱歌的方法
        String result = proxy.sing("只因你太美");
        System.out.println(result);

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

Java动态代理_第9张图片

 

你可能感兴趣的:(Java,java,代理模式,开发语言)