静态代理
看如下例子:
ICalculatorService 接口中代码如下
package com.jd.calculator;
public interface ICalculatorService {
//接口中的抽象方法,在CalculatorService中实现接口中的方法。
int add(int a, int b);
int sub(int a, int b);
int mul(int a, int b);
int div(int a, int b);
}
CalculatorService 实现了ICalculatorService 接口
package com.jd.calculator;
public class CalculatorService implements ICalculatorService {
@Override
public int add(int a, int b) {
System.out.println(this.getClass().getName()+":The add method begins.");
System.out.println(this.getClass().getName()+":Parameters of the add method: ["+a+","+b+"]");
int result = a+b;
System.out.println(this.getClass().getName()+":Result of the add method:"+result);
System.out.println(this.getClass().getName()+":The add method ends.");
return result;
}
@Override
public int sub(int a, int b) {
System.out.println(this.getClass().getName()+":The sub method begins.");
System.out.println(this.getClass().getName()+":Parameters of the sub method: ["+a+","+b+"]");
int result = a-b;
System.out.println(this.getClass().getName()+":Result of the sub method:"+result);
System.out.println(this.getClass().getName()+":The sub method ends.");
return result;
}
@Override
public int mul(int a, int b) {
System.out.println(this.getClass().getName()+":The mul method begins.");
System.out.println(this.getClass().getName()+":Parameters of the mul method: ["+a+","+b+"]");
int result = a*b;
System.out.println(this.getClass().getName()+":Result of the mul method:"+result);
System.out.println(this.getClass().getName()+":The mul method ends.");
return result;
}
@Override
public int div(int a, int b) {
System.out.println(this.getClass().getName()+":The div method begins.");
System.out.println(this.getClass().getName()+":Parameters of the div method: ["+a+","+b+"]");
int result = a/b;
System.out.println(this.getClass().getName()+":Result of the div method:"+result);
System.out.println(this.getClass().getName()+":The div method ends.");
return result;
}
}
Test中对上述代码进行操作:
package com.jd.test;
public class Test {
public static void main(String[] args) {
//简单的调用
CalculatorService calculatorService=new CalculatorService();
int result=calculatorService.add(2,3);
System.out.println(result);
}
}
输出如下结果:
我们可以看到,不论调用哪个方法,都会输出除了结果之外的四行代码,怎么样实现代码的复用,达到简化代码的效果?
动态代理(JDK)
下边用动态代理的方法实现简化代码:仅以检验add方法为例。
ICalculatorService 接口中代码如下
package com.jd.calculator;
public interface ICalculatorService {
int add(int a, int b);
}
CalculatorService中代码如下,实现了ICalculatorService 接口
package com.jd.calculator;
public class CalculatorService implements ICalculatorService {
@Override
public int add(int a, int b) {
int result = a+b;
return result;
}
}
Test中代码如下:
package com.jd.test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import com.jd.calculator.CalculatorService;
import com.jd.calculator.ICalculatorService;
import com.jd.calculator.ProxyFactory;
public class Test {
public static void main(String[] args) {
//动态代理的方法实现代码的复用。
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");//打印临时类文件代码。
CalculatorService calculatorService=new CalculatorService();
InvocationHandler handler=new InvocationHandler(){//匿名内部类对象
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//proxy为代理,method为要使用的方法,args为参数列表。
String name=method.getName();//获取要使用的方法名字。
System.out.println(calculatorService.getClass().getName()+":The "+name+" method begins.");
System.out.println(calculatorService.getClass().getName()+":Parameters of the "+name+" method: ["+args[0]+","+args[1]+"]");
Object result = method.invoke(calculatorService, args);//调用目标对象,即目标方法,此处为add方法。 //等价于calculatorService.add(args);
System.out.println(calculatorService.getClass().getName()+":Result of the "+name+" method:"+result);
System.out.println(calculatorService.getClass().getName()+":The "+name+" method ends.");
return result;
}
};
//ClassLoader classLoader=CalculatorService.class.getClassLoader();//类加载过程,实现相同的类加载。
ICalculatorService cService=(ICalculatorService) Proxy.newProxyInstance(calculatorService.getClass().getClassLoader(), calculatorService.getClass().getInterfaces(), handler);//1,用反射的方法创建动态代理;2,实现接口(与CalculatorService实现的相同);3,具体做什么。
int result=cService.add(3, 4);
System.out.println(result);
}
}
输出结果如下:
下边详述Test中代码执行过程:
先说明每一步代码的作用:
package com.jd.test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import com.jd.calculator.CalculatorService;
import com.jd.calculator.ICalculatorService;
import com.jd.calculator.ProxyFactory;
public class Test {
public static void main(String[] args) {
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");//打印临时类文件代码。
CalculatorService calculatorService=new CalculatorService();//创建calculatorService对象。
InvocationHandler handler=new InvocationHandler(){//匿名内部类对象,直接调用invoke方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//proxy为代理,method为要使用的方法,args为参数列表。
String name=method.getName();//获取要使用的方法名字。
System.out.println(calculatorService.getClass().getName()+":The "+name+" method begins.");
System.out.println(calculatorService.getClass().getName()+":Parameters of the "+name+" method: ["+args[0]+","+args[1]+"]");
Object result = method.invoke(calculatorService, args);//调用目标对象,即目标方法,此处为add方法。 //等价于calculatorService.add(args);
System.out.println(calculatorService.getClass().getName()+":Result of the "+name+" method:"+result);
System.out.println(calculatorService.getClass().getName()+":The "+name+" method ends.");
return result;
}
};
ICalculatorService cService=(ICalculatorService) Proxy.newProxyInstance(calculatorService.getClass().getClassLoader(), calculatorService.getClass().getInterfaces(), handler);//各个变量具体含义为:1),用反射的方法创建动态代理;2),实现接口(与CalculatorService实现的相同);3),具体做什么。
int result=cService.add(3, 4);//cService存的是由Proxy创建的实现了ICalculatorService的一个内部类,cService.add(arg,arg)其实是调用了由Proxy创建的匿名内部类对象中的add方法。
System.out.println(result);
}
}
内部类 $Proxy0 继承自 Proxy 实现了 ICalculatorService,所以实现了add方法。
代码执行过程为:创建了CalculatorService对象——》Proxy调用newProxyInstance方法得到Object对象,所以下转型,得到内部类对象 $Proxy0 ,实现了接口,所以重写了接口中的抽象方法——》handler为匿名内部类对象,直接调用invoke方法——》执行Object result = method.invoke(calculatorService, args);
此行代码,调用add方法int result=cService.add(3, 4);
传值——》返回结果——》输出结果。
接下来对上述代理模式进行简单的封装
创建一个ProxyFactory(代理工厂)类:
package com.jd.calculator;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyFactory {
static CalculatorService target;
static InvocationHandler handler=new InvocationHandler(){//匿名内部类对象
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//proxy为代理,method为要使用的方法,args为参数。
String name=method.getName();//获取要使用的方法名字。
System.out.println(target.getClass().getName()+":The "+name+" method begins.");
System.out.println(target.getClass().getName()+":Parameters of the "+name+" method: ["+args[0]+","+args[1]+"]");
Object result = method.invoke(target, args);//调用目标对象,即目标方法。
System.out.println(target.getClass().getName()+":Result of the "+name+" method:"+result);
System.out.println(target.getClass().getName()+":The "+name+" method ends.");
return result;
}
};
public static Object getProxy(CalculatorService target) {
ProxyFactory.target=target;//将传入的参数赋给成员变量,this.target=target;亦可以。
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), handler);
}
}
Test中代码如下
package com.jd.test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import com.jd.calculator.CalculatorService;
import com.jd.calculator.ICalculatorService;
import com.jd.calculator.ProxyFactory;
public class Test {
public static void main(String[] args) {
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
ICalculatorService calculatorService=(ICalculatorService)ProxyFactory.getProxy(new CalculatorService());//用反射的方法创建动态代理,实现接口(与CalculatorService实现的相同),干什么活
int result=calculatorService.add(3, 4);
System.out.println(result);
}
}
proxy继承自Proxy,实现了ICalculatorService 接口
动态代理(CGlib)
ICalculatorService,CalculatorService中代码与 动态代理(JDK)中相同。
目录如下
ProxyFactory 中代码如下
package com.zzu.calculator;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class ProxyFactory {
static CalculatorService target;//目标对象
static Callback callback=new MethodInterceptor(){//匿名内部类对象
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
String name=method.getName();//获取要使用的方法名字。
System.out.println(target.getClass().getName()+":The "+name+" method begins.");
System.out.println(target.getClass().getName()+":Parameters of the "+name+" method: ["+args[0]+","+args[1]+"]");
System.out.println(proxy.getClass().getSuperclass());
Object result = method.invoke(target, args);//调用目标对象,即目标方法。
System.out.println(target.getClass().getName()+":Result of the "+name+" method:"+result);
System.out.println(target.getClass().getName()+":The "+name+" method ends.");
return result;
}
};
public static Object getProxy(CalculatorService target) {
ProxyFactory.target=target;//将传入的参数赋给成员变量
Enhancer enhancer=new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(callback);
return enhancer.create();
}
}
Test中代码如下
proxy直接继承自CalculatorService
运行结果如下: