静态代理
请耐心看完这个笔记,我相信你能有所收获!看完就理解!
关系图是本人花费大量时间总结的,请不要白嫖哦~
暂时看不懂不要着急,结合代码就能明白!
如下是UserManager和 UserManagerImpl的代码:UserManagerImpl实现了UserManager。
以下只是作为演示。
public interface UserManager {
void addUser();
void delUser();
void findUser();
void modifyUser();
}
public class UserManagerImpl implements UserManager {
@Override
public void addUser() {
System.out.println("UserManagerImpl.addUser");
}
@Override
public void delUser() {
System.out.println("UserManagerImpl.delUser");
}
@Override
public void findUser() {
System.out.println("UserManagerImpl.findUser");
}
@Override
public void modifyUser() {
System.out.println("UserManagerImpl.modifyUser");
}
}
如果想要添加一个代理类,需要满足以下三个条件:
- 代理类实现接口
- 组合实现类
- 重写的每个方法里须嵌套方法(实现类对象的方法)
第三个条件实质上就是不改变原有业务的情况下,对原有业务进行拓展。比如下面这段代码:对其进行添加日志的功能。
public class UserManagerProxy implements UserManager{
UserManagerImpl userManager;//组合实现类
public void setUserManager(UserManagerImpl userManager) {
this.userManager = userManager;
}
@Override
public void addUser() {
try{
//添加打印日志的功能
//打印日志:开始添加用户
System.out.println("start-->addUser()");
userManager.addUser();
//打印日志:添加用户成功
System.out.println("success-->addUser()");
}catch(Exception e){
//打印日志:添加用户失败
System.out.println("error-->addUser()");
}
}
@Override
public void delUser() {
userManager.delUser();
}
@Override
public void findUser() {
userManager.findUser();
}
@Override
public void modifyUser() {
userManager.modifyUser();
}
}
此外,代理类还可以添加一些独有的方法,此时用户不仅可以访问代理类重写接口的所有的方法,还可以访问接口没有的代理对象的独有方法
public class Client {
public static void main(String[] args) {
UserManagerProxy proxy = new UserManagerProxy();
proxy.setUserManager(new UserManagerImpl());//通过set方法注入实现类对象,当然你也可以用构造器。
proxy.addUser();
}
}
用户被代理后,用户不再是访问原来的实现类,而是访问代理对象。
关系图
关系图详解:
用户被代理后,用户不再是访问原来的实现类,而是访问代理对象。
用户把需求交给代理对象,由代理对象去实现,我们就说代理对象代理了用户。
实现类把自己交给代理对象托管,让代理对象拓展我们原来实现类中的功能。
反过来,代理对象可以对实现类进行统一的管理,比如在本案例中调用具体实现类之前,用户说我需要打印日志,我们对调用实现类的方法前后加上添加打印日志的功能。这样就避免了修改具体实现类。满足我们所说的开闭原则。
优点:
- 代理对象拓展实现类的业务,而无需改变原来实现类的业务逻辑代码,遵循了面向对象的开闭原则。
- 此时用户不仅可以访问代理类重写接口的所有的方法,还可以访问接口没有的代理对象所独有的方法。
缺点:
但是实现类可能不止一个,假如我有100个这样的实现类,如果想让每个实现类都添加打印日志的功能的话,就需要添加100个对应的代理类,以及代理类中各个方法(4个方法,可能更多)都需要添加打印日志功能(如上的代理方法中删除,修改,以及查询都需要添加上打印日志的功能),难道我还要去100个代理类里去改4个方法吗。况且,假如用户又添加了10个需求,岂不是要改100410=4000次?是吧,显然很费效率。
总结就是:
静态代理类只能为特定的接口(Service)服务。如想要为多个接口服务则需要建立很多个代理类。
正因为静态代理如此缺点,由此我们引出了动态代理: