- 创建接口
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方法执行过程为
创建被代理类的对象
- 创建代理类对象,该类是一个实现了被代理类接口的实现类
- 把代理对象的类加载器和接口对象传入,最后一个参数为代理类需要执行的方法具体内容
- 通过InvocationHandler接口创建一个匿名内部类对象并重写invoke方法
该方法三个参数分别为1.代理类对象 2.被代理类的方法对象 3. 被代理类的方法参数 - 最后执行代理对象的方法,并返回结果
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
- 如果在接口中新增方法,只需要使用代理对象调用该方法即可,不需要再写额外的代码