11、代理
场景:
1、租房:包括房东(真实对象),中介(代理对象),客户(被代理对象)
-
房东:想要租房,只想租房,不想管带看房、签合同等操作。
- 租房接口:里面包含租房方法【因为不可能只有你一个人要租房】
- 房东类:里面实现了租房接口
-
中介:此时出现了中介,中介帮房东租房,包括带看房、签合同、以及获取自己的中间费用
- 中介类:同样实现租房接口,但是里面实现的方法是set房东类完成的,其他操作中介类自行添加
-
客户:客户不用去找房东,直接找中介,中介带你做你所需要的任何操作。
- 客户类:只需要new 中介类,就可以完成租房或者其他一系列操作
静态代理
实例测试静态代理模式
Why?
- UserDaoImpl实现了UserDao接口;
- 现有新的需求,要在每个实现的方法前添加日志
- 一般不能修改原有的代码,所以使用一个代理类,将所需要的一些代码切入进去
- 用户访问的时候,就直接访问代理类
- 代理类同样需要实现接口
UserDao
public interface UserDao {
//增
int add();
//删
int delete();
//查
List<User> select();
//改
int update();
}
UserDaoImpl
public class UserDaoImpl implements UserDao {
@Override
public int add() {
System.out.println("增");
return 0;
}
@Override
public int delete() {
System.out.println("删");
return 0;
}
@Override
public List<User> select() {
System.out.println("查");
return null;
}
@Override
public int update() {
System.out.println("改");
return 0;
}
}
StaticProxy
public class StaticProxy implements UserDao {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public int add() {
log("正在执行增加操作");
userDao.add();
return 0;
}
@Override
public int delete() {
log("正在执行删除操作");
userDao.delete();
return 0;
}
@Override
public List<User> select() {
log("正在执行查询操作");
userDao.select();
return null;
}
@Override
public int update() {
log("正在执行修改操作");
userDao.update();
return 0;
}
//需求:切入一段日志
private static void log(String msg){
System.out.println("[DEBUG]"+msg);
}
public void myMethod(){
System.out.println("这是我代理类特有的方法");
}
}
Test
@Test
public void test(){
//真实对象需要做的事情
UserDao userDao = new UserDaoImpl();
//需要一个代理对象
StaticProxy proxy = new StaticProxy();
//代理对象去代理真实类【set方法】
proxy.setUserDao(userDao);
//执行被代理对象需要执行的操作
proxy.add();
//代理对象还可以自己做一些额外的操作
proxy.myMethod();
}
好处:
不用修改自身原来的代码而动态实现代码的切入;
真实对象只需负责主要的业务,不用关心一些公共的业务,实现的业务的分工。
坏处:
静态代理一个真实对象就会产生一个代理对象,代码量增加,效率变低。
动态代理
动态代理的方式:
- 基于接口:JDK动态代理
- 基于类:cglib
- java字节码:javassist
动态代理需要了解2个类:
- Proxy:生成代理对象
- InvocationHandler:代理对象处理程序
- 实现该类,来创建代理对象和通过反射机制执行代理对象所要执行的操作
DynamicProxy
/**
* 动态代理的实现
*/
//用来创建代理对象,并执行代理程序
public class DynamicProxy implements InvocationHandler {
//代理类所需要代理的真实对象
private Object object;
public void setObject(Object object) {
this.object = object;
}
//获取代理对象
public Object getProxy(){
/**
* 参数一:生成代理对象的类加载器
* 参数二:代理类所要代理的接口
* 参数三:指实现InvocationHandler的类
*/
return Proxy.newProxyInstance(this.getClass().getClassLoader(),object.getClass().getInterfaces(),this);
}
//代理对象处理方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//使用代理类method去执行,参数一指的就是所需要代理的真实对象
Object invoke = method.invoke(object, args);
return invoke;
}
}
Test
@Test
public void test1(){
//真实对象所需要执行的操作
UserDao user = new UserDaoImpl();
//创建代理对象处理程序
DynamicProxy proxy = new DynamicProxy();
//设置所要代理的真实对象
proxy.setObject(user);
//创建代理对象
UserDao proxy1 = (UserDao) proxy.getProxy();
//执行
proxy1.add();
}
总结:静态代理和动态代理的区别?
静态代理:
一个类只能创建一个代理对象;
代理对象需要程序员自己手动创建;
动态代理
可研通过JDK原生接口,或者cglib包动态为所有类创建代理对象;
是动态创建的,不用自己手动创建;