【Java高级技术】动态代理

动态代理

1.程序为什么需要代理?

对象如果觉得自己干的事太多,可以通过代理转移一部分职责

2.代理要具备什么功能?

对象有什么方法想被代理,代理就一定要有对应的方法

Java通过接口(接口中提供被代理对象的抽象功能,由代理实现即可)来保证代理的样子

3.如何为Java创建一个代理对象?
  • java.lang.reflect.Proxy类:提供了为对象产生代理对象的方法

    public static Object newProxyInstance(ClassLoader loader,Class<?>[] interface,InvocationHandler h)
    
  • 参数一:loader:类加载器,作用是加载代理类

  • 参数二:interfaces:代理接口包含的内容,为数组形式

  • 参数三:h:传递InvocationHandler的实现类对象,用来指定代理对象的具体功能

  • 通过invokehandler的invoke方法指定代理干的事,这个invoke会被代理的方法在底层回调,参数需要接收(被代理的对象,invoke调用者所需要的参数(数组形式)

4.案例
  • 定义Star接口(保证代理的样子):提供抽象方法,表示需要代理的方法

    public interface Star {
        /**
         * @param songName 歌名
         * @return 唱完歌的反馈
         */
        public abstract String sing(String songName);
    
        /**
         * 跳舞,无参无返
         */
        public abstract void dance();
    }
    
  • 定义BigStar类:实现Star接口,重写Star中的抽象方法

    提供成员变量name,提供sing和dance方法

    public class BigStar implements Star {
    
        private String name;
    
        public BigStar(String name) {
            this.name = name;
        }
    
        @Override
        public String sing(String songName) {
            System.out.println(name + "正在唱:" + songName);
            return "谢谢大家~"; //唱完歌的反馈
        }
    
        @Override
        public void dance() {
            System.out.println(name + "正在优美的跳舞~");
        }
    }
    
  • 定义ProxyUtil类:提供静态方法创建代理,接收被代理对象(BigStar),多态返回代理对象Star

    (1)java提供的为对象创建代理的方法(三个参数)Proxy.newProxyInstance

    (2)重写后的invoke方法:用来指定代理对象的具体功能(回调方法:被sing和dance在底层调用)

    (3)返回代理对象

    public class ProxyUtil {
        public static Star createProxy(BigStar bigStar) {
            //java提供的为对象创建代理的方法(三个参数)
            Star starProxy = (Star) Proxy.newProxyInstance(
                    ProxyUtil.class.getClassLoader(),   //类加载器,作用是加载代理类
                    new Class[]{Star.class},            //代理接口包含的内容,为数组形式
                    new InvocationHandler() {        //InvocationHandler的实现类对象,用来指定代理对象的具体功能
           
                      @Override
                      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            //Object proxy:代理对象
                            //Method method:invoke的调用者,可能是sing方法,也可能是dance方法
                            //Object[] args:invoke调用者所需要的参数(数组形式)
    
                            //判断当前invoke的调用者
                            if (method.getName().equals("sing")) {
                                //代理要做的事
                                System.out.println("准备话筒,收钱..");
                            }else if(method.getName().equals("dance")){
                                //代理要做的事
                                System.out.println("准备场地,收钱..");
                            }
                            //代理做了该做的,剩余都由本尊做
                            return method.invoke(bigStar, args);
                        }
                    }
            );
    
            //返回代理对象
            return starProxy;
        }
    }
    
  • 测试类:通过ProxyUtil类获取代理对象,调用被代理的方法(sing、dance)

    public class Test {
        public static void main(String[] args) {
            Star starProxy = ProxyUtil.createProxy(new BigStar("周杰伦"));
            String result = starProxy.sing("晴天");
            System.out.println(result);
            System.out.println("--------------");
            starProxy.dance();
        }
    }
    

你可能感兴趣的:(java,开发语言)