代理模式是程序设计的一种设计模式。代理设计模式值的是在不修改源码的情况下,对原来的方法进行增强。通俗的来说就是将原来的代码交给代理对象来控制, 由代理对象来进行引用操作。
静态代理: 在程序运行前就已经存在的编译好的代理类是为静态代理,静态代理便于理解,但是缺点是所有方法都要手工实现,如果代理多个对象,重复代码会很多。
动态代理: 在程序运行期间根据需要动态创建代理类及其实例来完成具体的功能是为动态代理。
在java中动态代理目前使用比较多的有两种:
JDK动态代理
java.lang.reflect是java的"反射"包,提供了用于获取类和对象的反射信息的类和接口。
其中Proxy类就在java.lang.reflect包中,Proxy类利于反射实现代理模式,Java动态代理只能对接口进行代理,通过多态的性质,对实现该接口下所有类实现动态代理,所以动态代理实现我们并不清楚代理的类究竟是哪个,只有当运行的时候才能确定.
java.lang.reflect.InvocationHandler是JDK用来处理代理对象程序进行增强的接口类,我们通过继承该类,实现增强逻辑代码.
具体实例:
起床 和 睡觉 都要洗脸.
BaseService.java
public interface BaseService {
public void sleep();
public void getUp();
}
Person.java
public class Person implements BaseService {
@Override
public void sleep() {
System.out.println("睡觉");
}
@Override
public void getUp() {
System.out.println("起床");
}
}
Invocation.java
public class Invocation implements InvocationHandler {
private BaseService obj;//具体被监控对象
public Invocation(BaseService param){
this.obj =param;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(proxy == null){
throw new ServiceException("代理对象不可为null");
}
Object value;
String methodName = method.getName();
if("sleep".equals(methodName)){
value = method.invoke(this.obj,args);
wash();
} else if("getUp".equals(methodName)){
wash();
value = method.invoke(this.obj,args);
} else {
value = null;
}
return value; //返回被拦截方法,需要调用地方
}
public void wash(){
System.out.println("洗手");
}
}
ProxyFactory.java
public class ProxyFactory {
/**
* 为BaseService实例化代理对象。
* @param classFile
* @return
* @throws Exception
*/
public static BaseService Builder(Class classFile) throws Exception{
//1.创建被监控实例对象
BaseService obj = (BaseService)classFile.newInstance();
//2.创建一个通知对象 用接口来描述
InvocationHandler adviser = new Invocation(obj);
//3.向JVM申请负责监控obj对象指定行为的监控对象(代理对象)
/**
* loader:被监控对象隶属的类文件在内存中真实地址
* interfaces:被监控对象隶属的类文件实现接口
* h:监控对象发现小明要执行被监控行为,应该有哪一个通知对象进行辅助
*/
BaseService proxy = (BaseService) Proxy.newProxyInstance(
obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),
adviser);
return proxy;
}
}
TestProxy.java
public class TestProxy {
public static void main(String[] args) throws Exception {
BaseService jordan = ProxyFactory.Builder(Person.class);
jordan.getUp();
}
}
cglib动态代理
\