动态代理的基本理解与基本使用

  • 代理模式

代理模式,基本都懂吧。就例如我们平时去零售店买电脑。这个零售店其实就是代理商。它并不是直接生产电脑,而是帮一些生产电脑的厂商卖电脑,赚中间价。这就是代理模式。专业一点来说,在这里例子中,电脑厂就是被代理者,是真实对象。零售店就是代理者,是代理对象。代理模式就是,代理对象代理真实对象,达到增强真实对象的目的。

Java中的代理又分为静态代理与动态代理。

静态代理:简单地理解,就是有一个类文件来描述。

动态代理:在内存中形成代理类。

 

  • 动态代理的实现步骤

(1)代理对象和真实对象实现相同的接口。

示例:

// 接口

package com.chichung.proxy;

public interface SaleComputer {
    public String sale(double money);
}
// 真实对象实现接口

package com.chichung.proxy;

public class ComputerFactory implements SaleComputer {
    @Override
    public String sale(double money) {
        System.out.println(money+"厂家价");
        return "我是厂家";
    }
}

(2)代理对象 = Proxy.newProxyInstance()

示例:

package com.chichung.proxy;

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

public class ProxyTest {
    public static void main(String[] args) {
        ComputerFactory cf = new ComputerFactory();

        // 代理对象
        SaleComputer proxy_store = (SaleComputer) Proxy.newProxyInstance(cf.getClass().getClassLoader(), cf.getClass().getInterfaces(), new InvocationHandler() {

            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("hello");
                return null;
            }
        });

} }

Proxy.newProxyInstance()参数解析:

1.类加载器:真实对象.getClass().getClassLoader()

2.接口数组:真实对象.getClass().getInterfaces()

3.处理器:new InvocationHandler(){ ... }

 

(3)使用代理对象调用方法

package com.chichung.proxy;

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

public class ProxyTest {
    public static void main(String[] args) {
        ComputerFactory cf = new ComputerFactory();

        // 代理对象
        SaleComputer proxy_store = (SaleComputer) Proxy.newProxyInstance(cf.getClass().getClassLoader(), cf.getClass().getInterfaces(), new InvocationHandler() {

            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("hello");
                return null;
            }
        });

        String str = proxy_store.sale(8000);
        System.out.println(str);
    }
}

输出结果:

hello
null

为什么没有真实对象的打印以及返回?不急,看下去。

先说下invoke方法的几个参数:

1.proxy:代理对象

2.method:代理对象调用的方法,被封装为对象。获取方式:method.getName()

3.args:代理对象调用方法时,传递的实际参数。获取方式:args[0]

 

(4)增强对象

先实现一下没有增强对象,输出结果和原来真实对象直接调用方法一样的效果。

package com.chichung.proxy;

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

public class ProxyTest {
    public static void main(String[] args) {
        ComputerFactory cf = new ComputerFactory();

        // 代理对象
        SaleComputer proxy_store = (SaleComputer) Proxy.newProxyInstance(cf.getClass().getClassLoader(), cf.getClass().getInterfaces(), new InvocationHandler() {

            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Object obj = method.invoke(cf, args);    // 使用真实对象调用此方法
                return obj;
            }
        });

        String str = proxy_store.sale(8000);
        System.out.println(str);
    }
}

1.增强参数

package com.chichung.proxy;

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

public class ProxyTest {
    public static void main(String[] args) {
        ComputerFactory cf = new ComputerFactory();

        // 代理对象
        SaleComputer proxy_store = (SaleComputer) Proxy.newProxyInstance(cf.getClass().getClassLoader(), cf.getClass().getInterfaces(), new InvocationHandler() {

            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                if (method.getName().equals("sale")){
                    // 增强参数
                    Double money = (Double) args[0];
                    money = money * 1.25;
                    // 使用真实对象调用此方法
                    Object obj = method.invoke(cf, money);
                    return obj;
                }else {
                    // 使用真实对象调用此方法
                    Object obj = method.invoke(cf, args);
                    return obj;
                }
            }
        });

        String str = proxy_store.sale(8000);
        System.out.println(str);
    }
}

输出结果:

10000.0厂家价
我是厂家

2.增强返回值

package com.chichung.proxy;

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

public class ProxyTest {
    public static void main(String[] args) {
        ComputerFactory cf = new ComputerFactory();

        // 代理对象
        SaleComputer proxy_store = (SaleComputer) Proxy.newProxyInstance(cf.getClass().getClassLoader(), cf.getClass().getInterfaces(), new InvocationHandler() {

            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Object obj = method.invoke(cf, args);
                return obj+",一手货!!!";
            }
        });

        String str = proxy_store.sale(8000);
        System.out.println(str);
    }
}

输出结果:

8000.0厂家价
我是厂家,一手货!!!

3.增强方法体

package com.chichung.proxy;

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

public class ProxyTest {
    public static void main(String[] args) {
        ComputerFactory cf = new ComputerFactory();

        // 代理对象
        SaleComputer proxy_store = (SaleComputer) Proxy.newProxyInstance(cf.getClass().getClassLoader(), cf.getClass().getInterfaces(), new InvocationHandler() {

            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                if (method.getName().equals("sale")){
                    System.out.println("走过路过别错过");
                    Double money = (Double) args[0];
                    money = money * 1.25;
                    // 使用真实对象调用此方法
                    Object obj = method.invoke(cf, money);
                    System.out.println("手快有手慢没");
                    return obj;
                }else {
                    // 使用真实对象调用此方法
                    Object obj = method.invoke(cf, args);
                    return obj;
                }
            }
        });

        String str = proxy_store.sale(8000);
        System.out.println(str);
    }
}

输出结果:

走过路过别错过
10000.0厂家价
手快有手慢没
我是厂家

原文地址:https://www.cnblogs.com/chichung/p/10358444.html