1.什么是代理模式?
即Proxy Pattern,是Java的23种设计模式之一。是Spring中AOP(面向切面编程)的底层。
官方回答是:对其它对象提供一种代理以控制对这个对象的访问。
通俗易懂的讲:一个专职于做某件事情的方法只去做它本身该做的事情,其余的事情可以交给其他方法去做,也就是在不改变这个方法本身的基础上对这个方法进行增强。
这么讲还是有点抽象。接下来我举一个简单的例子:
有位同学和他的女友相识在一个美丽的夜晚,从最初的相识,到之后的相知,然后相爱,如今要步入婚姻的殿堂了。这时出现一个问题:总所周知,结婚本身就是一件耗费精力的事情,更不要说筹划婚宴的场景布置之类的种种琐事。这时婚庆公司出现了,(理想情况下:)他们的专业团队可以帮这位同学解决他的烦恼,也就是代理二位新人去做一些事情,让二位新人只专注于结婚本身。
上述例子中出现了四类角色:
抽象角色:结婚这件事情(抽象的方法或接口)
实现角色:实现结婚这件事情(具体的实现方法)
代理角色:布置婚宴的婚庆公司(对方法进行增强)
客户角色:委托婚庆中心的新人(通过代理调用实现的方法)
2.代理模式的优势
1.可以让方法更纯粹,不再关注自身之外的公共业务。
2.职责分明,减少代码的冗余。
3.方便于公共业务的管理。
3.静态代理实现
1.抽象角色:
/**
* 服务接口
*/
public interface Service {
void insert();
void delete();
void update();
void select();
}
2.实现角色:
/**
* 服务实现类
*/
public class ServiceImpl implements Service{
@Override
public void insert() {
System.out.println("insert");
}
@Override
public void delete() {
System.out.println("delete");
}
@Override
public void update() {
System.out.println("update");
}
@Override
public void select() {
System.out.println("select");
}
}
3.代理角色:
/**
* 服务代理类
*/
public class Proxy {
private Service service;
public void setService(Service service) {
this.service = service;
}
public void insert() {
System.out.println("insert run");
service.insert();
}
public void delete() {
System.out.println("delete run");
service.delete();
}
public void update() {
System.out.println("update run");
service.update();
}
public void select() {
System.out.println("select run");
service.select();
}
}
4.客户角色:
/**
* 使用静态代理
*/
@Test
public void demo02(){
Service service = new ServiceImpl();
Proxy proxy = new Proxy();
proxy.setService(service);
proxy.insert();
proxy.delete();
proxy.update();
proxy.select();
}
运行结果:
细心的同学可能就会发现:
每使用一次代理我们都要写一个对应的代理类,工作量加大辣!开发效率变低辣!
如何解决?
接着往下看!
3.动态代理
所谓动态代理即是通过一些手段动态生成我们的代理类,我们再也不必投入大量的精力去编写代理类辣!
首先我们要清楚的是:动态代理的底层使用的是Java的反射机制。
实现动态代理,需要用到Java jdk提供的两个API:Proxy类和InvocationHandler接口。
以下是对动态代理的实现。
1.动态代理处理器:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 动态代理处理器
* 1.实现InvocationHandler接口
* 2.实现接口invoke方法
* 3.生成代理对象
* 4.编写invoke方法代码
*/
public class ProxyInvocationHandler implements InvocationHandler {
/**
* 被代理的接口对象
*/
private Object object;
/**
* 提供set方法
* @param object
*/
public void setObject(Object object) {
this.object = object;
}
/**
* 生成代理对象
* @return
*/
public Object getProxy(){
/**
* this.getClass().getClassLoader() 获取类反射对象
* object.getClass().getInterfaces() 获取 被代理的接口 的接口
* this 当前类
*/
return Proxy.newProxyInstance(this.getClass().getClassLoader(), object.getClass().getInterfaces(), this);
}
/**
* 处理代理示例,并返回结果
* @param proxy
* @param method
* @param args
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//在原方法前增强:
System.err.println("我要增强你!");
//执行被代理的接口的方法
Object invoke = method.invoke(object, args);
//在原方法后增强:
System.err.println("我增强完辣!");
//最后记得返回!
return invoke;
}
}
2.动态代理处理器的使用:
/**
* 使用动态代理
*/
@Test
public void demo03(){
//1.创建要动态代理的对象
Service service = new ServiceImpl();
//2.创建动态代理处理器对象
ProxyInvocationHandler handler = new ProxyInvocationHandler();
//3.通过set方法将要增强的对象注入
handler.setObject(service);
//4.调用getProxy获取动态代理对象
Service proxy = (Service) handler.getProxy();
//5.通过代理对象调接口方法
proxy.select();
}
运行结果: