(2)代理模式
来源:互联网 发布:动态海报制作软件 编辑:程序博客网 时间:2024/06/06 18:10
代理模式分为两种,一种静态代理,一种动态代理
一、静态代理
静态代理在我们生活中其实非常常见,比如买票,当火车站太远而且需要排队,这个时候就需要一个手机来在网上买票了,这种情况下手机就相当于火车站的代理对象,还有比如说追女孩,我想送一束花,因为跟女孩不太熟,直接送会显得很突兀,这时就需要委托一个人来帮忙送了,这个人此时就相当于我的代理对象。
代码说明
将人抽象成一个类
public abstract Boy{ void sendFlowers();}
我要追的女孩需要实现这个接口
public class Me extends Boy { @Override public void sendFlowers() { System.out.println("送给女孩一朵花"); }}
直接送会很尴尬,所以委托别人帮我送
public class MeProxy extends Boy { //需要穿入被代理对象的引用 private Boy boy; public MeProxy (Boy boy) { this.boy = boy; } @Override public void sendFlowers() { boy.sendFlowers(); System.out.println("委托者说你先把花给我然后我转交她"); }}
测试类
public class Test { public static void main(String[] args) { Me me = new Me(); MeProxy meproxy = new Meproxy(me); meproxy.sendFlowers(); }}
二、动态代理
动态代理又分为两种,一种jdk动态代理,一种是cglib动态代理
jdk动态代理
首先定义一个接口
public interface Car { int run(); void drive();}
被代理类实现接口
public class MyCar implements Car { @Override public int run() { System.out.println("我的车速度很快"); return 80; } @Override public void drive() { System.out.println("安全第一,严禁酒驾"); }}
代理类继承InvocationHandler接口来给方法做增强
public class MyInvocationHandler implements InvocationHandler { //传入被代理类的引用 private MyCar myCar; public MyInvocationHandler(MyCar myCar) { this.myCar = myCar; } @Override public Object invoke(Object object, Method method, Object[] args) throws Throwable { if (method.getName() == "drive") { System.out.println("上车请系好安全带"); Object invoke = method.invoke(myCar, args); System.out.println("下车请锁好车"); return invoke; } return method.invoke(myCar, args); }}
测试类
public static void main(String[] args) { MyCar myCar = new MyCar(); /** * myInvocationHandler 实现了 InvocationHandler 接口,并能实现方法调用从代理类到委托类的分派转发 * 其内部通常包含指向委托类实例的引用,用于真正执行分派转发过来的方法调用. * 即:要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象来调用其方法 */ MyInvocationHandler myInvocationHandler = new MyInvocationHandler(myCar); Object object = Proxy.newProxyInstance(myCar.getClass().getClassLoader(), myCar.getClass().getInterfaces(),myInvocationHandler ); Car car = (Car) object; car.drive(); car.run(); }
运行结果如下
JDK动态代理和CGLIB的区别
Aspect默认情况下不用实现接口,但对于目标对象,在默认情况下必须实现接口
如果没有实现接口必须引入CGLIB库
我们可以通过Advice中添加一个JoinPoint参数,这个值会由spring自动传入,从JoinPoint中可以取得
参数值、方法名等等
1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP
3、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换
如何强制使用CGLIB实现AOP?
* 添加CGLIB库,SPRING_HOME/cglib/*.jar
* 在spring配置文件中加入
JDK动态代理和CGLIB字节码生成的区别?
* JDK动态代理只能对实现了接口的类生成代理,而不能针对类
* CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法
因为是继承,所以该类或方法最好不要声明成final
- 设计模式(2)-代理模式
- 代理模式2
- 代理模式(2)
- 代理模式2
- 2.1.2 代理模式
- (2)代理模式
- 代理模式设计(2)-----动态代理
- 代理模式之静态代理(2)
- 设计模式(2) 代理模式 静态代理
- 设计模式 - 代理、外观(2)
- 第 2 章 代理模式
- 2、代理模式(Proxy)
- java设计模式(2)---代理模式
- 设计模式之2---代理模式
- 设计模式之禅-代理模式2
- 代理模式--动态代理
- 代理模式-静态代理
- 代理模式-静态代理
- Java开发中的23种设计模式详解(转)
- Java项目导出可运行的jar文件
- Python曲线平滑
- Ubuntu16.04安装wps并解决系统缺失字体问题
- git学习心得
- (2)代理模式
- MongoDB用户的角色权限
- Extjs 下拉框combo实现显示框和下拉框加背景色
- Java 类加载机制详解
- Java 编程思想 第3章课后习题解答
- linux中'.'的作用
- C和指针第五章笔记
- 可替代Visio绘制工作流程图,有哪些?
- Sublime Text 3 输入法(Fcitx)