JDK——动态代理

  • 创建接口
public interface ICalculatorService {
	int add(int a,int b);
}
  • 接口实现类
public class CalculatorService implements ICalculatorService {
	@Override
	public int add(int a, int b) {
		int result = a+b;
		return result;
	}
}
  • 创建一个Test类给add方法添加日志信息或者其他信息
@Override
	public int add(int a, int b) {
		String name = method.getName();
		System.out.println(target.getClass().getName()+":The "+name+" method begins.");
		System.out.println(target.getClass().getName()+":Parameters of the sub method: ["+args[0]+","+args[1]+"]");
		int result = a+b;
		System.out.println(target.getClass().getName()+":Result of the sub method:"+result);
		System.out.println(target.getClass().getName()+":The sub method ends.");
		return result;
	}

通过该类可提高代码复用率,避免日志等信息和主要的业务代码糅合在了一起,代码变得较为臃肿。

  • 创建Test类
public class Test {
	public static void main(String[] args) {
		//一、创建需要被代理的对象
		ICalculator calculator = new Calculator();
		InvocationHandler handler = new InvocationHandler() {
			@Override
			//三、代理类对象对应方法具体执行内容
			//该方法一共三个参数
			//第一个参数是calculator的代理对象
			//第二个参数是被代理类的方法的对象
			//第三个参数是上面方法对应的参数列表
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				System.out.println(calculator.getClass().getName()+":The "+method.getName()+" method begins.");
				System.out.println(calculator.getClass().getName()+":Parameters of the "+method.getName()+" method: ["+args[0]+","+args[1]+"]");
				Object result = method.invoke(calculator, args);
				System.out.println(calculator.getClass().getName()+":Result of the "+method.getName()+" method:"+result);
				System.out.println(calculator.getClass().getName()+":The "+method.getName()+" method ends.");
				return result;
			}
		};
		//二、创建代理对象调用Proxy中的静态方法,创建一个被代理的类实现的接口的一个实现类
		//该方法需要传入三个参数分别为
		//1.被代理类的类加载器
		//2.被代理实现的接口
		//3.代理类需要执行的相关方法
		ICalculator calculatorProxy = (ICalculator) Proxy.newProxyInstance(calculator.getClass().getClassLoader(), calculator.getClass().getInterfaces(), handler);
		int result = calculatorProxy.add(1, 1);
		System.out.println(result);
	}
}
  • 执行结果

com.dz.calculator.Calculator:The add method begins.
com.dz.calculator.Calculator:Parameters of the add method: [10,5]
com.dz.calculator.Calculator:Result of the add method:15
com.dz.calculator.Calculator:The add method ends.
2
其中的add方法执行过程为

创建被代理类的对象

  1. 创建代理类对象,该类是一个实现了被代理类接口的实现类
  2. 把代理对象的类加载器和接口对象传入,最后一个参数为代理类需要执行的方法具体内容
  3. 通过InvocationHandler接口创建一个匿名内部类对象并重写invoke方法
    该方法三个参数分别为1.代理类对象 2.被代理类的方法对象 3. 被代理类的方法参数
  4. 最后执行代理对象的方法,并返回结果

JDK 1.8已经支持Lambda表达式所以也可以使用Lambda表达式来简化代码

public class Test {
	public static void main(String[] args) {
		ICalculator calculator = new Calculator();
		InvocationHandler handler = (Object proxy, Method method, Object[] parameters) -> {
				System.out.println(calculator.getClass().getName()+":The "+method.getName()+" method begins.");
				System.out.println(calculator.getClass().getName()+":Parameters of the "+method.getName()+" method: ["+parameters[0]+","+parameters[1]+"]");
				Object result = method.invoke(calculator, parameters);
				System.out.println(calculator.getClass().getName()+":Result of the "+method.getName()+" method:"+result);
				System.out.println(calculator.getClass().getName()+":The "+method.getName()+" method ends.");
				return result;
		};
		ICalculator calculatorProxy = (ICalculator) Proxy.newProxyInstance(calculator.getClass().getClassLoader(), calculator.getClass().getInterfaces(), handler);
		int result = calculatorProxy.add(10, 5);
		System.out.println(result);
	}
}

可以在代码的中添加代码,保存生成的代理类的Class文件

System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");

注意:执行之后需要refresh项目,否则在eclipse中看不见生成的.class文件。

  • 对生成的.class文件进行反编译
package com.sun.proxy;

import com.dz.calculator.ICalculator;
import java.lang.reflect.*;

//实现了ICalculator接口
public final class $Proxy0 extends Proxy implements ICalculator
{

    public $Proxy0(InvocationHandler invocationhandler)
    {
        super(invocationhandler);
    }

    public final boolean equals(Object obj)
    {
        try
        {
            return ((Boolean)super.h.invoke(this, m1, new Object[] {
                obj
            })).booleanValue();
        }
        catch(Error _ex) { }
        catch(Throwable throwable)
        {
            throw new UndeclaredThrowableException(throwable);
        }
    }

    public final String toString()
    {
        try
        {
            return (String)super.h.invoke(this, m2, null);
        }
        catch(Error _ex) { }
        catch(Throwable throwable)
        {
            throw new UndeclaredThrowableException(throwable);
        }
    }

	//生成的add方法
    public final int add(int i, int j)
    {
        try
        {	
        	//执行h就是传入的handler匿名内部类对象的重写的invoke方法
            return ((Integer)super.h.invoke(this, m3, new Object[] {Integer.valueOf(i), Integer.valueOf(j)})).intValue();
        }
        catch(Error _ex) { }
        catch(Throwable throwable)
        {
            throw new UndeclaredThrowableException(throwable);
        }
    }

    public final int hashCode()
    {
        try
        {
            return ((Integer)super.h.invoke(this, m0, null)).intValue();
        }
        catch(Error _ex) { }
        catch(Throwable throwable)
        {
            throw new UndeclaredThrowableException(throwable);
        }
    }

    private static Method m1;
    private static Method m2;
    private static Method m3;
    private static Method m0;

    static 
    {
        try
        {
            m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] {
                Class.forName("java.lang.Object")
            });
            m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
            //m3为add方法对应的Method对象
            m3 = Class.forName("com.dz.calculator.ICalculator").getMethod("add", new Class[] {
                Integer.TYPE, Integer.TYPE
            });
            m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
        }
        catch(NoSuchMethodException nosuchmethodexception)
        {
            throw new NoSuchMethodError(nosuchmethodexception.getMessage());
        }
        catch(ClassNotFoundException classnotfoundexception)
        {
            throw new NoClassDefFoundError(classnotfoundexception.getMessage());
        }
    }
}

对代理类进行优化

public class ProxyFactory {
	static Calculator target ;
	
	InvocationHandler handler =	new InvocationHandler() {
		@Override
		public Object invoke(Object proxy, Method method, Object[] parameters) throws Throwable {
			System.out.println(target.getClass().getName()+":The "+method.getName()+" method begins.");
			System.out.println(target.getClass().getName()+":Parameters of the "+method.getName()+" method: ["+parameters[0]+","+parameters[1]+"]");
			Object result = method.invoke(target, parameters);
			System.out.println(target.getClass().getName()+":Result of the "+method.getName()+" method:"+result);
			System.out.println(target.getClass().getName()+":The "+method.getName()+" method ends.");
			return result;
		}
	};
	
	public Object getProxy(Calculator target) {
		ProxyFactory.target = target;
		return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), handler);
	}
}

测试

public class TestProxy {
	public static void main(String[] args) {
		ProxyFactory factory = new ProxyFactory();
		Calculator calculator = new Calculator();
		ICalculator proxy = (ICalculator) factory.getProxy(calculator);
		int result = proxy.add(1, 2);
		System.out.println(result);
	}
}

结果

com.dz.calculator.Calculator:The add method begins.
com.dz.calculator.Calculator:Parameters of the add method: [3,2]
com.dz.calculator.Calculator:Result of the add method:5
com.dz.calculator.Calculator:The add method ends.
3

  • 如果在接口中新增方法,只需要使用代理对象调用该方法即可,不需要再写额外的代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值