1.1 动态代理
- 动态代理的角色和静态代理的一样, 动态代理的代理类是动态生成的 . 静态代理的代理类是提前写好的。
- 动态代理分为两类 : 一类是基于接口动态代理 , 一类是基于类的动态代理。
- 基于接口的动态代理----JDK动态代理。
- 基于类的动态代理–cglib。
- 现在用的比较多的是 javasist 来生成动态代理 . 百度一下javasist。
JDK的动态代理需要了解两个类 : InvocationHandler 和 Proxy
InvocationHandler【调用处理程序】
Object invoke(Object proxy, 方法 method, Object[] args);
//参数
//proxy - 调用该方法的代理实例
//method -所述方法对应于调用代理实例上的接口方法的实例。 方法对象的声明类将是该方法声明的接
口,它可以是代理类继承该方法的代理接口的超级接口。
//args -包含的方法调用传递代理实例的参数值的对象的阵列,或null如果接口方法没有参数。 原始
类型的参数包含在适当的原始包装器类的实例中,例如java.lang.Integer或java.lang.Boolean
。
Pxoxy【代理】
//生成代理类
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
rent.getClass().getInterfaces(),this);
}
1.2 代码示例
Rent接口(抽象角色)
package cn.guardwhy.domain;
// 抽象角色:租房
public interface Rent {
public void rent();
}
Landlord
package cn.guardwhy.domain;
// 真实角色: 房东,要出租房子
public class Landlord implements Rent {
@Override
public void rent() {
System.out.println("房屋出租!!!");
}
}
ProxyInvocationHandler 即代理角色
package cn.guardwhy.proxy;
import cn.guardwhy.domain.Rent;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 该类自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {
// 1.被代理的接口
private Rent rent;
public void setRent(Rent rent) {
this.rent = rent;
}
// 2.生成得到代理类
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
rent.getClass().getInterfaces(), this);
}
// 3.处理代理实例,并且返回结果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
seeHouse();
// 动态代理的本质。就是使用反射机制实现
Object result = method.invoke(rent, args);
fare();
return result;
}
// 4.方法
public void seeHouse(){
System.out.println("带房客看房...");
}
// 收中介费
public void fare(){
System.out.println("收中介费");
}
}
Client(租客)
package cn.guardwhy.client;
import cn.guardwhy.domain.Landlord;
import cn.guardwhy.domain.Rent;
import cn.guardwhy.proxy.ProxyInvocationHandler;
public class Client {
public static void main(String[] args) {
// 1.真实角色
Landlord landlord = new Landlord();
// 2.代理角色
ProxyInvocationHandler pith = new ProxyInvocationHandler();
// 3.通过调用程序处理角色来处理要调用的接口对象
pith.setRent(landlord);
Rent proxy = (Rent) pith.getProxy();
// 4.调用接口
proxy.rent();
}
}
执行结果
总结
一个动态代理 , 一般代理某一类业务 , 一个动态代理可以代理多个类,代理的是接口。
1.3 深化动态代理
UserService
package cn.guardwhy.domain;
// 抽象角色,增删改查业务
public interface UserService {
void add();
void delete();
void update();
void query();
}
UserServiceImpl
package cn.guardwhy.domain;
// 真实对象,完成增删改查的操作
public class UserServiceImpl implements UserService {
@Override
public void add() {
System.out.println("增加了一个用户");
}
@Override
public void delete() {
System.out.println("删除了一个用户");
}
@Override
public void update() {
System.out.println("更新了一个用户");
}
@Override
public void query() {
System.out.println("查询一个用户");
}
}
编写一个通用的动态代理实现的类!所有的代理对象设置为Object。
package cn.guardwhy.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyInvocationHandler2 implements InvocationHandler {
// 1.被代理的接口
private Object target;
// 2.set注入
public void setTarget(Object target) {
this.target = target;
}
// 3.生成得到代理类
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
// 4.处理代理实例,并且返回结果
@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 + "方法" );
}
}
Client(租客)
package cn.guardwhy.client;
import cn.guardwhy.domain.UserService;
import cn.guardwhy.domain.UserServiceImpl;
import cn.guardwhy.proxy.ProxyInvocationHandler2;
public class Client2 {
public static void main(String[] args) {
//1.真实角色
UserServiceImpl userService = new UserServiceImpl();
//2.代理对象的调用处理程序
ProxyInvocationHandler2 pith = new ProxyInvocationHandler2();
//3.设置要代理的对象
pith.setTarget(userService);
// 动态生成代理类
UserService proxy = (UserService) pith.getProxy();
//4.调用方法
proxy.add();
}
}
执行结果
1.4 动态代理的好处
静态代理有的它都有,静态代理没有的,它也有!
- 可以使得我们的真实角色更加纯粹 . 不再去关注一些公共的事情 。
- 公共的业务由代理来完成 . 实现了业务的分工 ,
- 公共业务发生扩展时变得更加集中和方便 .
- 动态代理 , 一般代理某一类业务,一个动态代理可以代理多个类,代理的是接口。