/**
* 通过 java.lang.reflect.Proxy 实现动态代理基本写法
*
* 由于代理类实现代理功能的模式基本相同,所以我们可以写一个通用的方法去代理所有的实现类
*
* 实现大致思路(动态编译):
* 1、通过String去拼 XxxProxy.java 文件中的代码
* 2、生成文件
* 3、编译 运行 返回结果
* (JVM底层直接拼接字节码来生成结果)
*
* 实现过程类似于js中的 eval('alert()') 方法
*
* 调用:
* 1、创建接口、实体类
* 2、创建对应实体类的 Handler 类,重写 invoke 方法,添加前后逻辑
* 3、通过 Proxy.newProxyInstance() 生成代理类
* 4、通过代理类执行方法
*/
public class DynamicProxy2 {
public static void main(String[] args) {
test1();
}
public static void test1(){
Aircraft a = new Aircraft();
AircraftHandler ah = new AircraftHandler(a);
IFlyable proxy = (IFlyable) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),
new Class[]{IFlyable.class}, ah);
proxy.fly();
}
}
interface IFlyable{
public void fly();
}
class Aircraft implements IFlyable{
@Override
public void fly(){
for(int i=1;i<5;i++){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("飞机飞行"+i*100+"米....");
}
}
}
class AircraftHandler implements InvocationHandler{
Aircraft a;
public AircraftHandler(Aircraft a){
this.a = a;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object object = null;
if("fly".equals(method.getName())){
System.out.println("开始计时....");
System.out.println("[log]开始日志记录");
long start = System.currentTimeMillis();
object = method.invoke(a, args);
long end = System.currentTimeMillis();
System.out.println("[log]结束日志记录");
System.out.println("计时结束 共运行"+(end-start));
}
return object;
}
}
/**
* 通过 java.lang.reflect.Proxy 实现动态代理
*
* 1、定义公共接口
* 2、定义真实对象 继承接口 实现功能
* 3、定义方法处理实现类(TimeHandler/LogHandler)
*
* 拥有静态代理的优点,同时实现了 实现类 和 代理类 的分离(TimeHandler/LogHandler 可用于任何被代理类)
* 接口修改后只需修改具体的实现类,不需要修改代理类
* 比 静态代理 重用性更好,维护性更好
*/
public class DynamicProxy3 {
public static void main(String[] args) {
test1();
System.out.println("-----------------------------");
test2();
System.out.println("-----------------------------");
test3();
System.out.println("-----------------------------");
test4();
}
/**
* Tank 先进行时间记录,再进行log记录
*/
public static void test1(){
Tank t = new Tank();
LogHandler lh = new LogHandler(t);
IMoveable logProxy = (IMoveable)Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),
new Class[]{IMoveable.class}, lh);
TimeHandler th = new TimeHandler(logProxy);
IMoveable timeProxy = (IMoveable)Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),
new Class[]{IMoveable.class}, th);
timeProxy.move();
}
/**
* Tank 先进行log记录,再进行时间记录
*/
public static void test2(){
Tank t = new Tank();
TimeHandler th = new TimeHandler(t);
IMoveable timeProxy = (IMoveable)Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),
new Class[]{IMoveable.class}, th);
LogHandler lh = new LogHandler(timeProxy);
IMoveable logProxy = (IMoveable)Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),
new Class[]{IMoveable.class}, lh);
logProxy.move();
}
/**
* Aircraft 先进行时间记录,再进行log记录
*/
public static void test3(){
Aircraft a = new Aircraft();
LogHandler lh = new LogHandler(a);
IFlyable logProxy = (IFlyable)Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),
new Class[]{IFlyable.class}, lh);
TimeHandler th = new TimeHandler(logProxy);
IFlyable timeProxy = (IFlyable)Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),
new Class[]{IFlyable.class}, th);
timeProxy.fly();
}
/**
* Aircraft 先进行log记录,再进行时间记录
*/
public static void test4(){
Aircraft a = new Aircraft();
TimeHandler th = new TimeHandler(a);
IFlyable timeProxy = (IFlyable)Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),
new Class[]{IFlyable.class}, th);
LogHandler lh = new LogHandler(timeProxy);
IFlyable logProxy = (IFlyable)Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),
new Class[]{IFlyable.class}, lh);
logProxy.fly();
}
}
/**
* 记录时间具体实现
*/
class TimeHandler implements InvocationHandler{
Object obj;
public TimeHandler(Object o){
this.obj = o;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object object = null;
System.out.println("方法"+method.getName()+"开始调用 开始计时....");
long start = System.currentTimeMillis();
object = method.invoke(obj, args);
long end = System.currentTimeMillis();
System.out.println("方法"+method.getName()+"调用结束 用时"+(end-start));
return object;
}
}
/**
* 记录日志具体实现
*/
class LogHandler implements InvocationHandler{
Object obj;
public LogHandler(Object o){
this.obj = o;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object object = null;
System.out.println("[log]记录"+method.getName()+"方法开始调用日志");
object = method.invoke(obj, args);
System.out.println("[log]记录"+method.getName()+"方法结束调用日志");
return object;
}
}