动态代理主要有两种实现方式 :
- 基于接口的动态代理 : JDK动态代理
- 基于类的动态代理 : cglib
下面演示的是 JDK动态代理
1 JDK动态代理需要了解的一个接口和一个类
1.1 InvocationHandler (调用处理程序)
InvocationHandler 是生成代理实例的类需要实现的接口,然后需要实现接口中的 invoke() 方法,在这个方法中进行对代理实例的处理
1.2 Proxy (代理)
Proxy 是所有代理实例的父类,它提供了创建动态代理实例的静态方法.
2 代码演示一
2.1 创建一个抽象对象
//租房
public interface Rend {
public void rend();
}
2.2 创建一个 真实对象
public class Homeowner implements Rend {
@Override
public void rend(){
System.out.println("房东出租了房子");
}
}
3.3 创建一个生成代理实例的类(核心)
//这个类是用来生成代理实例的类
public class ProxyInvocationHandle implements InvocationHandler {
//被代理的接口
private Rend rend;
public void setRend(Rend rend) {
this.rend = rend;
}
//生成得到代理类
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),rend.getClass().getInterfaces(),this);
}
//处理代理实例,并返回结果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//动态代理的本质,就是使用反射机制实现!
seeHouse();
Object result = method.invoke(rend, args);
fare();
return result;
}
public void seeHouse(){
System.out.println("中介带你看房子");
}
public void fare(){
System.out.println("收中介费");
}
}
3.4 创建客户类
public class Client {
public static void main(String[] args) {
//真实角色
Homeowner homeowner = new Homeowner();
//代理角色:现在没有
ProxyInvocationHandle pih = new ProxyInvocationHandle();
//通过调用程序处理角色来处理我们要调用的接口对象!
pih.setRend(homeowner);
Rend proxy = (Rend) pih.getProxy();//这里的proxy就是动态生成的,我们并没有写
proxy.rend();
}
}
3.5 执行结果
3 代码演示二
3.1 创建一个抽象对象
public interface UserService {
public void query();
public void add();
public void delete();
public void update();
}
3.2 创建一个真实对象
public class UserServiceImpl implements UserService{
@Override
public void query() {
System.out.println("查询用户");
}
@Override
public void add() {
System.out.println("增加用户");
}
@Override
public void delete() {
System.out.println("删除用户");
}
@Override
public void update() {
System.out.println("修改用户");
}
}
3.3 创建一个生成代理实例的类(核心)
//用这个类,自动生成代理类
public class ProxyInvocationHandle implements InvocationHandler {
//被代理的接口
private Object target;
public void setTarget(Object target) {
this.target = target;
}
//生成得到代理类
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
//处理代理实例,并返回结果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//动态代理的本质,就是使用反射机制实现!
log(method.getName());
Object result = method.invoke(target, args);
return result;
}
public void log(String msg){
System.out.println("执行了"+msg+"方法");
}
}
3.4 创建客户类
public class Client {
public static void main(String[] args) {
//真实角色
UserServiceImpl userService = new UserServiceImpl();
//代理角色,不存在
ProxyInvocationHandle pih = new ProxyInvocationHandle();
pih.setTarget(userService);//设置要代理的对象
//动态生成代理类
UserService proxy = (UserService) pih.getProxy();
proxy.add();
}
}
3.5 执行结果
4 总结
- 动态代理解决了静态代理创建过多的代理类导致开发效率降低的问题
- 动态代理的角色和静态代理的是相同的
- 动态代理的代理类是动态生成的 . 静态代理的代理类是我们提前写好的
- 一个动态代理 , 一般代理某一类业务
- 一个动态代理可以代理多个类,代理的是接口
- 可以使得我们的真实角色更加纯粹 . 不再去关注一些公共的事情
- 公共的业务由代理来完成 . 实现了业务的分工
- 公共业务发生扩展时变得更加集中和方便