为什么要学习代理模式?因为这是SpringAOP的底层!
代理模式的分类:
一、静态代理
角色分析:
- 抽象角色:一般会使用接口和抽象类来解决。
- 真实角色:被代理的角色。
- 代理角色:代理真实角色,代理真实角色后,我们会做一些附属的操作。
- 客户:访问代理对象的人!
代码步骤:
1.1 接口
1 2 3
| public interface Rent { public void rent(); }
|
1.2 真实角色
1 2 3 4 5 6 7
| public class Host implements Rent{ @Override public void rent() { System.out.println("房东要租房子"); } }
|
1.3 代理角色
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public class Proxy implements Rent{ private Host host; public Proxy() { } public Proxy(Host host) { this.host = host; } @Override public void rent() { host.rent(); seeHouse(); fare(); } private void seeHouse(){ System.out.println("中介带你看房"); } private void fare(){ System.out.println("收中介费"); } }
|
1.4 客户端访问代理角色
1 2 3 4 5 6 7 8 9 10
| public class Client { public static void main(String[] args) { Host host = new Host(); Proxy proxy = new Proxy(host); proxy.rent(); }
|
代理模式的好处:
- 可以使真实角色的操作更加纯粹
- 公共业务就交给了代理角色!实现了业务的分工!
- 公共业务发生扩展的时候,方便集中管理!
缺点:
二、代理模式Demo2
2.1 接口
1 2 3 4 5 6
| public interface UserService { public void add(); public void delete(); public void update(); public void query(); }
|
2.2 真实角色
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| 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("查询用户"); } }
|
2.3 代理角色
在不改动真实角色代码的情况下,对真实的功能进行扩展。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| public class UserServiceProxy implements UserService{ UserService userService;
public UserServiceProxy(UserService userService) { this.userService = userService; }
@Override public void add() { log("add"); userService.add(); }
@Override public void delete() { log("delete"); userService.delete(); }
@Override public void update() { log("update"); userService.update(); }
@Override public void query() { log("query"); userService.query(); } public void log(String msg){ System.out.println("[Debug] 使用"+msg+"方法"); } }
|
2.4 客户端访问代理
1 2 3 4 5 6 7
| public class MyTest { public static void main(String[] args) { UserServiceImpl userService = new UserServiceImpl(); UserServiceProxy userServiceProxy = new UserServiceProxy(userService); userServiceProxy.add(); } }
|
三、动态代理
- 动态代理和静态代理角色一样。
- 动态代理的代理类是动态生成的,不是我们直接写好的。
- 动态代理分为两大类:基于接口的动态代理,基于类的动态代理。
- 基于接口 — JDK动态代理
- 基于类:cglib
- java字节码实现:javasist
需要了解两个类:Proxy:代理,InvocationHandler:调用处理程序
- Proxy:提供创建动态代理类和实例的静态方法。
- InvocationHandler:调用处理程序并返回结果。
3.1 技术原型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public class ProxyInvocationHandler implements InvocationHandler {
private Object target;
public void setTarget(Object target) { this.target = target; } public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this); }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = method.invoke(target, args); return result; } }
|
1 2 3 4 5 6 7 8 9 10 11
| public static void main(String[] args) { Host host =new Host(); ProxyInvocationHandler pih = new ProxyInvocationHandler(); pih.setTarget(host); Rent proxy = (Rent) pih.getProxy(); proxy.rent(); }
|
动态代理的好处:
- 一个动态代理类代理的是一个接口,一般就是对应的一类业务。
- 一个动态代理类可以代理多个类,只要是实现同一个接口即可。
3.2 实例
3.2.1 接口
1 2 3 4 5 6
| public interface UserService { public void add(); public void delete(); public void update(); public void query(); }
|
3.2.2 接口实现类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| 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("查询用户"); } }
|
3.2.3 动态代理类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public class ProxyInvocationHandler implements InvocationHandler { UserService userService; public void setUserService(UserService userService) { this.userService = userService; } public UserService getProxy(){ UserService proxy = (UserService) Proxy.newProxyInstance(this.getClass().getClassLoader(), userService.getClass().getInterfaces(), this); return proxy; }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { log(method.getName()); Object result = method.invoke(userService, args); return result; } public void log(String msg){ System.out.println("[Debug] 使用"+msg+"方法"); } }
|
测试
1 2 3 4 5 6 7 8 9 10
| public static void main(String[] args) { UserServiceImpl userService = new UserServiceImpl(); ProxyInvocationHandler pih = new ProxyInvocationHandler(); pih.setUserService(userService); UserService proxy = pih.getProxy(); proxy.add(); }
|