Java代理的优势是实现无侵入式的代码扩展,也就是方法的增强;让你可以在不用修改源码的情况下,增强一些方法;在方法的前后你可以做你任何想做的事情
静态代理
package proxy;
public class People implements Sleep{
public static void main(String[] args) {
Sleep s = new People();
Sleep ptp = new PeopleTimeProxy(s);
Sleep plp = new PeopelLogProxy(ptp);
plp.sleep();
}
@Override
public void sleep() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class PeopleTimeProxy implements Sleep{
Sleep s;
public PeopleTimeProxy(Sleep s) {
this.s = s;
}
@Override
public void sleep() {
long start = System.currentTimeMillis();
s.sleep();
long end = System.currentTimeMillis();
System.out.println(end-start);
}
}
class PeopelLogProxy implements Sleep{
Sleep s;
public PeopelLogProxy(Sleep s) {
this.s = s;
}
@Override
public void sleep() {
System.out.println("start sleep");
s.sleep();
System.out.println("wake up");
}
}
interface Sleep {
void sleep();
}
start sleep
1001
wake up
代理固定类型对象
动态代理
package proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class God implements Sleep{
public static void main(String[] args) {
God g = new God();
Sleep s = (Sleep)Proxy.newProxyInstance(g.getClass().getClassLoader(),
new Class[] {Sleep.class},new LogHandler(g));
s.sleep();
}
@Override
public void sleep() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class LogHandler implements InvocationHandler{
God g;
public LogHandler(God g) {
this.g = g;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("method "+method.getName() + " start");
Object o = method.invoke(g, args);
System.out.println("method "+method.getName()+ " end");
return o;
}
}
interface Sleep{
void sleep();
}
method sleep start
method sleep end
动态代理的实现使用Proxy.newProxyInstance()
,方法的三个参数为类加载器、实现的接口对象的class数组、实现了InvocationHandler
接口的类的实例。
在实现的InvocationHandler
接口的类中的invoke
方法中指定操作,jdk会自动生成实现第二个参数class数组中所有接口的类,然后返回一个实例。
在jdk生成的类中需要实现的方法中都会调用第三个参数的所定义的invoke
方法三个参数为jdk所生成的类的实例、用反射获取的main中所执行的方法、方法所需要的参数
在我们自己定义的invoke
中用反射调用传入的方法的invoke
方法并指定执行的对象和参数。