代理模式
关于代理,代理模式可以避免客户端对原对象的直接操作,客户端通过一个代理类来访问原对象,代理类可以基于这个原理增强对原对象的控制,可以使用措施保护原对象,或者针对该原对象,扩展一些额外的功能,如记录日志等,
代理模式示例
这种代理,原对象和代理类 必须实现同一个接口
public interface Action { //需要原对象和代理类都实现的接口
void a();
}
public class MyObject implements Action{ // 原对象
MyObject(){
}
@Override
public void a() {
System.out.println("I have a action");
}
}
public class ProxyObject implements Action{
MyObject myObject;
ProxyObject(){
myObject = new MyObject();
}
@Override
public void a() {
System.out.println("I am log"); // 代理类可以在这个位置做对原对象的动作控制
myObject.a();
}
}
public class Test {
public static void main(String[] args){
Action prxoy = new ProxyObject();
prxoy.a();
}
}
print:
I am log
I have a action
Java中的代理
静态代理
上面的示例
动态代理
在jvm运行时动态生成的一个代理,代理类不必实现与原对象相同的接口,原对象是必须实现接口的
/**
* 代理类
*/
public class DynamicProxy {
private Object target;// 维护一个目标对象
public DynamicProxy(Object target) {
this.target = target;
}
// 为目标对象生成代理对象
public Object getProxyInstance() {
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("log start");
Object returnValue = method.invoke(target, args);
System.out.println("log end");
return null;
}
});
}
}
/**
*
*/
public class TestDynamicProxy {
public static void main(String[] args){
Action myObject = (Action) new DynamicProxy(new MyObject()).getProxyInstance();
myObject.a();
}
}
print:
log start
I have a action
log end
cglib代理
这是个三方扩展包,可以看到上述的两种代理模式,均需要某一方实现接口,但是cglib代理的对象无需实现接口。Spring中就使用了该三方包,用于AOP
public class NoInterfaceObject {
public void aaaa(){
System.out.println("aaaaa");
}
}
public class CglibProxy implements MethodInterceptor{
private Object target;
public CglibProxy(Object target) {
this.target = target;
}
public Object getProxyInstance() {
Enhancer en = new Enhancer();
en.setSuperclass(target.getClass()); //Cglib 使用子类继承的方式来代理原对象类
en.setCallback(this); //设置回调,当原对象有动作触发时,调用intercept方法
return en.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("log start");
Object returnValue = method.invoke(target, args);
System.out.println("log end");
return null;
}
}
public class TestCglibProxy {
public static void main(String[] args){
NoInterfaceObject noInterfaceObject = (NoInterfaceObject) new CglibProxy(new NoInterfaceObject()).getProxyInstance();
noInterfaceObject.aaaa();
}
}
print:
log start
aaaaa
log end
我们看到代理类使用子类继承的方式代理原对象类,这也说明如果我们的原对象类有final修饰的话,那就不行了