1、有一个接口,
/**
* 移动接口
* @author Administrator
*
*/
public interface Moveable {
void move();
}
有一个实现类--》坦克类
/**
* 模拟坦克
* 实现移动接口
* @author Administrator
*
*/
public class Tank implements Moveable {
@Override
public void move() {
System.out.println("Tank moving...");
}
}
2、当需要对move方法做日志处理,但是不能改动源码,怎么办?
这里引入静态代理,静态代理类需要是接口的实现类,还需要包含该接口的成员变量
/**
* 计算未知源码方法的另一种方式
* 聚合,代理,更好
* 使用代理,可以加判断,检测是否有调用方法的权限
* 可以记录调用方法的相关日志
* @author Administrator
*
*/
public class TankLogProxy implements Moveable {
Moveable m;
public TankLogProxy(Moveable m){
super();
this.m = m;
}
@Override
public void move() {
System.out.println("Tank is start...");
m.move();
System.out.println("Tank is end...");
}
}
3、但是,我们不仅需要对该方法做日志处理,还需要做异常处理、事务控制、权限认证,
这个时候,需要引入动态代理,这样我们就可以只处理业务逻辑就可以
查看Java API,它有相应的接口,我们可以直接实现,然后动态生成我们需要的代理类,
/**
* 动态代理
* 生成各种代理对象的工厂
* @author Administrator
*
*/
public class ProxyFactory implements InvocationHandler {
private Object target;
public ProxyFactory(Object target){
this.target = target;
}
public Object getTarget() {
return target;
}
public void setTarget(Object target) {
this.target = target;
}
public Object productProxyObject(){
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);
}
/**
* Object proxy代理类
* Method method代理类的方法
* Object[] args方法的参数
* 被代理的方法调用处
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("方法执行之前");
Object result = method.invoke(target, args);
System.out.println("方法执行之后");
return result;
}
}
4、查看API,
Proxy
提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
-
参数:
-
loader
- 定义代理类的类加载器 -
interfaces
- 代理类要实现的接口列表 -
h
- 指派方法调用的调用处理程序
InvocationHandler
是代理实例的调用处理程序 实现的接口。
-
参数:
-
proxy
- 在其上调用方法的代理实例 -
method
- 对应于在代理实例上调用的接口方法的Method
实例。Method
对象的声明类将是在其中声明方法的接口,该接口可以是代理类赖以继承方法的代理接口的超接口。 -
args
- 包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,则为null
。基本类型的参数被包装在适当基本包装器类(如java.lang.Integer
或java.lang.Boolean
)的实例中。
有空研究下。