为什么要学习代理模式? 因为这就是SpringAOP的底层! [SpringAOP和SpringMVC]
代理模式的分类:
-
静态代理
-
动态代理
10.1 静态代理
角色分析:
-
抽象角色 : 一般会使用接口或者抽象类来解决
-
真实角色 : 被代理的角色
-
代理角色 : 代理真实角色,代理真实角色后,我们一般会做一些附属操作
-
客户 : 访问代理对象的人!
没有代理时:
抽象角色:租房
真实角色:房东
客户:租房的人
代理时:
抽象角色:租房
真实角色:房东
代理角色:中介
客户:租房的人
代码步骤:
1.接口
package com.chang.demo01; public interface Rent { void rent(); }
2.真实角色
public class Host implements Rent{ public void rent() { System.out.println("房东要出租房子!"); } }
3.代理角色
package com.chang.demo01; public class Proxy implements Rent{ private Host host; public Proxy(Host host) { this.host = host; } public Proxy() { } public void rent() { seeHouse(); host.rent(); hetong(); fare(); } //看房 public void seeHouse(){ System.out.println("中介带你看房"); } //租赁 public void hetong(){ System.out.println("签租赁合同"); } //收中介费 public void fare(){ System.out.println("收中介费"); } }
4.客户端访问代理角色
package com.chang.demo01; public class Client { public static void main(String[] args) { //房东要租房子 Host host = new Host(); //代理,中介帮房东出租房子,但是代理角色一般会有一些附属操作 Proxy proxy = new Proxy(host); //你不用面对房东,直接找中介即可 proxy.rent(); } }
代理模式的好处:
-
可以使真实角色的操作更加纯粹!不用去关注一些公共的业务
-
公共业务也就交给代理角色!实现了业务的分工!
-
公共业务发生扩展的时候,方便集中管理!
代理模式的缺点:
-
一个真实角色就会产生一个代理角色: 代码量会翻倍~开发效率会变低
10.2 加深理解
业务练习:
首先需要一个接口,里面为增删改查方法
package com.chang.demo02; public interface UserService { void add(); void delete(); void update(); void query(); }
然后一个实现类
package com.chang.demo02; public class UserServiceImpl implements UserService { public void add() { System.out.println("add"); } public void delete() { System.out.println("delete"); } public void update() { System.out.println("update"); } public void query() { System.out.println("query"); } }
测试一个
package com.chang.demo02; import sun.nio.cs.US_ASCII; public class Client { public static void main(String[] args) { UserServiceImpl userService = new UserServiceImpl(); userService.add(); } }
结果:
成功执行了!,但是,如果现在有一个需求是在每一个方法执行的之前,需要输出一条日志,日志内容为对应的方法执行了,这怎么办呢?
首先可以考虑暴力的方法,就是每一个方法都写加一个输出语句
package com.chang.demo02; public class UserServiceImpl implements UserService { public void add() { System.out.println("[DEBUG]add方法执行了"); System.out.println("add"); } public void delete() { System.out.println("[DEBUG]delete方法执行了"); System.out.println("delete"); } public void update() { System.out.println("[DEBUG]update方法执行了"); System.out.println("update"); } public void query() { System.out.println("[DEBUG]query方法执行了"); System.out.println("query"); } }
这样显然是可以成功的,但是代码有点重复!可以改进吗,还可以写一个方法,然后调用方法!
package com.chang.demo02; import java.net.SocketTimeoutException; public class UserServiceImpl implements UserService { public void add() { debug("add"); System.out.println("add"); } public void delete() { debug("delete"); System.out.println("delete"); } public void update() { debug("update");; System.out.println("update"); } public void query() { debug("query"); System.out.println("query"); } public void debug(String msg){ System.out.println("[DEBUG]"+msg+"执行了"); } }
但是还有一个,能不能不改变原有代码就达到同样的效果呢?
这就需要用到了代理模式
我们需要创建一个代理类,里面需要一个具体的被代理对象
提供一个set方法,参数为被代理对象的类型
再代理对象中完成对应的操作
需要变的就是客户端和再多加一个代理类
代理类
package com.chang.demo02; public class UserServiceProxy implements UserService{ private UserServiceImpl userService; public UserServiceProxy(UserServiceImpl userService) { this.userService = userService; } public void add() { System.out.println("[DEBUG]add方法执行了"); userService.add(); } public void delete() { System.out.println("[DEBUG]delete方法执行了"); userService.delete(); } public void update() { System.out.println("[DEBUG]update方法执行了"); userService.update(); } public void query() { System.out.println("[DEBUG]query方法执行了"); userService.query(); } }
客户端
package com.chang.demo02; import sun.nio.cs.US_ASCII; public class Client { public static void main(String[] args) { UserServiceImpl userService = new UserServiceImpl(); UserServiceProxy proxy = new UserServiceProxy(userService); proxy.add(); } }
结果:
也是成功的完成了! 可能会有很多人说这我在原来的类中加不就行了吗,但是这样不需要改变原来代码,只需要横切就行了
底层AOP就是使用了这种设计模式
如果说的有不太对的地方请大佬指教