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

Posted chichung

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态代理的基本理解与基本使用相关的知识,希望对你有一定的参考价值。

  • 代理模式

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

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厂家价
手快有手慢没
我是厂家

 









以上是关于动态代理的基本理解与基本使用的主要内容,如果未能解决你的问题,请参考以下文章

动态代理详解

深入理解Spring AOP之二代理对象生成

精心收集的 48 个 JavaScript 代码片段,仅需 30 秒就可理解!(转载)

百度T7:深入理解Java动态代理与代码模拟JDK实现动态代理JAVA核心

动态代理模式1--基本使用

class文件的基本结构及proxy源码分析二