代理模式
概述:为某个对象提供代理类,用来控制对这个对象的访问,委托类与代理类有一个共同的父类或父接口,代理类会对请求做预处理、过滤,将请求分配给指定对象。
代理三要素
- 有共同的行为
- 目标角色
- 代理角色
静态代理
特点
- 目标角色固定
- 应用程序执行前获得目标角色
- 代理对象会增强目标角色的行为
- 多个代理会出现类爆炸
实现
- 定义父类接口
- 委托类是是实现父接口
- 代理类实现父接口,并其中含有委托类对象属性
- 代理在重写的方法中加入增强行为同时调用委托类的方法
动态代理
概述:动态代理类的字节码是在程序运行期间,通过反射动态生成的,可以根据需要动态生成代理对象。可以同时代理多个方法,在满足生产需要的同时又达到代码通用的目的。
特点:
- 目标角色不固定
- 应用程序执行时动态创建目标对象
- 代理对象可以增强目标对象
实现方式:
- JDK动态代理(接口实现)
- CGLIB动态代理(继承思想)
JDK
动态代理
使用
Proxy
类的newProxyInstance()
,是专门完成代理的操作类,可以为一个或多个接口生成实现类,
newProxyInstance(ClassLoder loader,Class<?>[]interface,InvocationHandler h)
专门用于生成代理对象参数解释:
ClassLoader
:指定为那个类生成代理对象Class<?>[] interface
:接口数组,表示需要代理对象的接口,让代理类也是先这个接口InvocationHandler h
:表示代理实例的调用处理程序实现的接实现过程:
- 实现
InvocationHandler
接口- 定义目标对象,并生成构造器
- 重新给invoke()方法,其中是增强方法
- 获取代理对象,通过
Proxy.newProxyInstance()
CGLIB
动态代理:
概述:有些类不能实现接口,想要实现代理则必须要使用
CGLIB
动态代理,对指定的目标生成一个子类,并覆盖其中的方法实现增强。使用方式:
- 添加相关依赖,
cglib
- 定义生成动态代理的类,定义代理的目标角色,并为其生成构造器
- 生成代理对象,通过
Enhancer
类生成代理类,首先是生成一个类,设置其父类(目标角色),设置拦截器,通过create()方法生成一个代理类对象- 实现
MethodInterceptor
接口,重写interceptor(Object object, Method method, Object[] objects, MethodProxy methodProxy)
方法其中含有增强行为,参数含义
object
:CGLIB
代理对象method
:共同的父类objects
:参数列表methodProxy
:生成的代理对象对方法进行代理
JDK
动态代理与CGLIB
动态代理的区别:
JDK
动态代理依赖接口实现,CGLIB
动态代理依赖继承JDK
动态代理比CGLIB
动态代理效率要高- 委托类含有接口实现,则使用
JDK
动态代理;不含有接口实现,使用CGLIB
动态代理
SPring-AOP
作用:日志记录,性能统计,安全控制等重复使用的功能。
特点:
- 高内聚低耦合
- 提高了代码的复用性
- 增强了系统的可扩展性
- 同时可以在不影响系统原有功能的前提下,为类添加新的方法或属性
底层实现:动态代理JDK
以及CGLIB
基本概念:
JoinPoint
连接点:被拦截的每个方法Pointcute
:切入点,拦截规则advice
- 前置通知
- 返回通知
- 异常抛出通知
- 最终通知
- 环绕通知
Aspect
:切面target
:目标角色weave
:织入,切面应用到目标对象并生成代理对象的过程Introduction
:不修改原应用程序的基础上,为类动态的添加方法或者属性(在程序运行期间)
注解实现
- 添加坐标依赖
aspectjweaver
- 添加spring.xml配置
- 定义切面类,类上添加
@Aspect
声明当前类为一个切面- 定义切入点(切入规则)
@Pointcut("匹配规则")
- 执行任意公共方法:
execution(public *(..))
- 执行任意set方法:
execution(* set*(..))
- 执行任意包下的任意类的任意方法:
execution(* com.xx.service.*.*(..))
- 执行指定包下的任意类的任意子包的任意方法:
execution(* com.xxxx.service..*.*(..))
- 通知注解:
- 前置通知:
@Before(value="")
- 返回通知:
@AfterReturning(value="")
- 最终通知:
@After(value="")
- 异常抛出通知:
@AfterThrowing(value="",throwing="e")
- 环绕通知:
@Around(value="")
- 配置文件配置AOP代理:
<aop:aspectj-autoproxy/>
XML实现
实现步骤上同:
但是注入是在XML配置文件中完成的:
<asp:config> <asp:aspect ref="切面类名"> 定义切入规则 各种通知配置 </asp:aspect> </asp:config>
拓展:SpringTask
作用是:进行固定时间执行指定任务,优点是功能强大,使用简单
使用方式:
XML配置使用:
定义定时工作类,加上
@Component
注解XML文件中设置,
<!--添加的xmlns--> xmlns:task="http://www.springframework.org/schema/task" http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd <!--设置自动扫描注解--> <context:component-scan base-package="包名"></context:component-scan> <!--注入定时执行事件--> <task:scheduled-tasks> <!--每隔2秒执行一次--> <task:scheduled ref="定时任务id" method="定时任务(方法)" cron="(0/2 * * * * ?)"></task:scheduled> </task:scheduled-tasks>
调用中测试(注意要在main方法中测试):
代理模式
概述:为某个对象提供代理类,用来控制对这个对象的访问,委托类与代理类有一个共同的父类或父接口,代理类会对请求做预处理、过滤,将请求分配给指定对象。
代理三要素
- 有共同的行为
- 目标角色
- 代理角色
静态代理
特点
- 目标角色固定
- 应用程序执行前获得目标角色
- 代理对象会增强目标角色的行为
- 多个代理会出现类爆炸
实现
- 定义父类接口
- 委托类是是实现父接口
- 代理类实现父接口,并其中含有委托类对象属性
- 代理在重写的方法中加入增强行为同时调用委托类的方法
动态代理
概述:动态代理类的字节码是在程序运行期间,通过反射动态生成的,可以根据需要动态生成代理对象。可以同时代理多个方法,在满足生产需要的同时又达到代码通用的目的。
特点:
- 目标角色不固定
- 应用程序执行时动态创建目标对象
- 代理对象可以增强目标对象
实现方式:
- JDK动态代理(接口实现)
- CGLIB动态代理(继承思想)
JDK
动态代理
使用
Proxy
类的newProxyInstance()
,是专门完成代理的操作类,可以为一个或多个接口生成实现类,
newProxyInstance(ClassLoder loader,Class<?>[]interface,InvocationHandler h)
专门用于生成代理对象参数解释:
ClassLoader
:指定为那个类生成代理对象Class<?>[] interface
:接口数组,表示需要代理对象的接口,让代理类也是先这个接口InvocationHandler h
:表示代理实例的调用处理程序实现的接实现过程:
- 实现
InvocationHandler
接口- 定义目标对象,并生成构造器
- 重新给invoke()方法,其中是增强方法
- 获取代理对象,通过
Proxy.newProxyInstance()
CGLIB
动态代理:
概述:有些类不能实现接口,想要实现代理则必须要使用
CGLIB
动态代理,对指定的目标生成一个子类,并覆盖其中的方法实现增强。使用方式:
- 添加相关依赖,
cglib
- 定义生成动态代理的类,定义代理的目标角色,并为其生成构造器
- 生成代理对象,通过
Enhancer
类生成代理类,首先是生成一个类,设置其父类(目标角色),设置拦截器,通过create()方法生成一个代理类对象- 实现
MethodInterceptor
接口,重写interceptor(Object object, Method method, Object[] objects, MethodProxy methodProxy)
方法其中含有增强行为,参数含义
object
:CGLIB
代理对象method
:共同的父类objects
:参数列表methodProxy
:生成的代理对象对方法进行代理
JDK
动态代理与CGLIB
动态代理的区别:
JDK
动态代理依赖接口实现,CGLIB
动态代理依赖继承JDK
动态代理比CGLIB
动态代理效率要高- 委托类含有接口实现,则使用
JDK
动态代理;不含有接口实现,使用CGLIB
动态代理
SPring-AOP
作用:日志记录,性能统计,安全控制等重复使用的功能。
特点:
- 高内聚低耦合
- 提高了代码的复用性
- 增强了系统的可扩展性
- 同时可以在不影响系统原有功能的前提下,为类添加新的方法或属性
底层实现:动态代理JDK
以及CGLIB
基本概念:
JoinPoint
连接点:被拦截的每个方法Pointcute
:切入点,拦截规则advice
- 前置通知
- 返回通知
- 异常抛出通知
- 最终通知
- 环绕通知
Aspect
:切面target
:目标角色weave
:织入,切面应用到目标对象并生成代理对象的过程Introduction
:不修改原应用程序的基础上,为类动态的添加方法或者属性(在程序运行期间)
注解实现
- 添加坐标依赖
aspectjweaver
- 添加spring.xml配置
- 定义切面类,类上添加
@Aspect
声明当前类为一个切面- 定义切入点(切入规则)
@Pointcut("匹配规则")
- 执行任意公共方法:
execution(public *(..))
- 执行任意set方法:
execution(* set*(..))
- 执行任意包下的任意类的任意方法:
execution(* com.xx.service.*.*(..))
- 执行指定包下的任意类的任意子包的任意方法:
execution(* com.xxxx.service..*.*(..))
- 通知注解:
- 前置通知:
@Before(value="")
- 返回通知:
@AfterReturning(value="")
- 最终通知:
@After(value="")
- 异常抛出通知:
@AfterThrowing(value="",throwing="e")
- 环绕通知:
@Around(value="")
- 配置文件配置AOP代理:
<aop:aspectj-autoproxy/>
XML实现
实现步骤上同:
但是注入是在XML配置文件中完成的:
<asp:config> <asp:aspect ref="切面类名"> 定义切入规则 各种通知配置 </asp:aspect> </asp:config>
拓展:SpringTask
作用是:进行固定时间执行指定任务,优点是功能强大,使用简单
使用方式:
XML配置使用:
定义定时工作类,加上
@Component
注解XML文件中设置,
<!--添加的xmlns--> xmlns:task="http://www.springframework.org/schema/task" http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd <!--设置自动扫描注解--> <context:component-scan base-package="包名"></context:component-scan> <!--注入定时执行事件--> <task:scheduled-tasks> <!--每隔2秒执行一次--> <task:scheduled ref="定时任务id" method="定时任务(方法)" cron="(0/2 * * * * ?)"></task:scheduled> </task:scheduled-tasks>
调用中测试(注意要在main方法中测试):
注解形式(推荐使用):
在定时任务上添加
@Scheduled(cron="(0/2 * * * * ?)")
注解,使用cron表达式规定定时任务执行时间。同时在XML配置文件中加上:
<task:annotation-driven/>
配置定时任务驱动
注解形式(推荐使用):
在定时任务上添加
@Scheduled(cron="(0/2 * * * * ?)")
注解,使用cron表达式规定定时任务执行时间。同时在XML配置文件中加上:
<task:annotation-driven/>
配置定时任务驱动