思考问题:别人面向UserDao接口写好的类(UserDaoImpl)(你不得修改别人代码),你需要对这个类的方法记录日志或检查权限以确定其他调用者是否有权限使用该方法时你该怎么设计?(或记录调用日志)
解答:自己设计一个日志类(UserDaoLogProxy),将UserDao组合进去(就是UserDaoLogProxy添加一个UserDao属性),然后添加与UserDao类的方法名相同的所有方法,在每个方法中添加权限检查或日志信息后再调用UserDao的相同的方法。这样暴露给其他调用者的UserDaoLogProxy类就是已经实现了日志检查的类了,其他调用者就可以通过UserDao u = new UserDaoLogProxy()来使用到你实现的日志功能或权限功能了。这就是代理模式;
实例:
UserDao接口:
package com.shusheng.proxy;
/**访问数据库的dao层*/
public interface UserDao {
//添加用户
public boolean insert(User user);
}
UserDaoImpl类:
package com.shusheng.proxy;
/**假设这是时别人已经实现好的类*/
public class UserDaoImpl implements UserDao{
/**将用户插入到数据库*/
@Override
public boolean insert(User user) {
System.out.println("将user 插入到数据库中");
return true;
}
}
代理类:
package com.shusheng.proxy;
/**假设这是实现了记录日志的userDao代理类*/
public class UserDaoLogProxy implements UserDao{
UserDao userDao;
//构造代理类时需要传入被代理的对象
public UserDaoLogProxy(UserDao userDao) {
this.userDao = userDao;
}
@Override
public boolean insert(User user) {
this.log();//记录日志
return userDao.insert(user);
}
private void log() {
System.out.println("记录日志");
}
}
测试类(模拟上层调用者):
package com.shusheng.proxy;
/**这个类可以模拟调用UserDao类的service类*/
public class ProxyTest {
public static void main(String[] args) {
UserDao userDao = new UserDaoImpl();//未使用代理,无法记录日志
System.out.println(userDao.insert(new User())+"\n");
userDao = new UserDaoLogProxy(userDao);//代理类记录日志
System.out.println(userDao.insert(new User()));
}
}
(实现权限检查同理。)
动态代理与静态代理的区别:
上面这种实现方式称为静态代理,该代理只能代理UserDaoImpl类,但是类似spring框架中不可能为每一个类添加静态代理(会导致类大爆炸的),所以就有了动态代理的概念Proxy,我们把被代理的类传入到Proxy类的方法中,就可以返回一个被代理的对象,而且代理对象实现的业务还可以自己规定(在InvocationHandler中实现)。比如实现权限检查等,动态代理模式在我博客中也有单独介绍,欢迎探讨。
时间: 2024-10-13 07:33:58