代理模式
静态代理
角色分析:
抽象角色:一般使用接口或抽象类来实现。一是通过继承被代理类的方式实现其子类,重写父类方法;二是与被代理类实现共同的一个接口。
真实角色:被代理的角色。
代理角色:代理真实角色,执行附属操作。
客户:使用代理角色来进行一些操作。
代码步骤 :
1、接口
1 | public interface Rent { |
2、真实角色
1 | public class Host implements Rent { |
3、代理角色
1 | public class Proxy { |
4、客户端访问代理角色
1 | public class Client { |
好处:
1、可以使真实角色的操作更加纯粹,不用去关注其他公共的业务
2、公共业务交给代理角色,实现业务分工
3、公共业务发生拓展时,方便集中管理
缺点:
一个真实角色就会产生一个代理角色,造成代码量翻倍
动态代理
代理类是动态生成的,不是我们直接写好的。交给程序去自动生成代理类(在程序运行期间由JVM根据反射等机制动态的生成源码 )。
动态代理分为两大类:基于接口的JDK动态代理;基于类cglib动态代理。
1、接口
1 | public interface UserService { |
2、真实角色
1 | public class UserServiceImpl implements UserService { |
3、实现InvocationHandler接口
1 | public class MyInvocationHandler implements InvocationHandler { |
4、创建并使用代理对象
1 | public class Client { |
动态代理作用:
1、在目标类源代码不改变的情况下,增加功能。
2、减少代码重复
3、专注业务逻辑代码
4、解耦合
AOP定义
面向切面编程,基于动态代理,可使用jdk,cglib两种代理方式。
Spring会根据具体的Bean是否具有实现接口去选择动态代理方式,如果有接口,使用的是Jdk的动态代理方式,如果没有接口,使用的是cglib的动态代理方式。
AOP就是动态代理的规范化,供开发人员以统一的方式使用动态代理。
比如你写了个方法用来做一些事情,但这个事情要求登录用户才能做,你就可以在这个方法执行前验证一下,执行后记录下操作日志,把前后的这些与业务逻辑无关的代码抽取出来放一个类里,这个类就是切面(Aspect),这个被环绕的方法就是切点(Pointcut),你所做的执行前执行后的这些方法统一叫做增强处理(Advice)。
面向切面编程实现:
1、需要在分析项目功能时,找出切面
2、合理的安排切面的执行时间(目标方法前,还是目标方法后)—->通知注解
3、合理的安排切面执行的位置(在哪个类,哪个方法增加增强方法)—->切入点表达式
AOP实现
aspectj:开源的aop实现框架
加入aspectj依赖
1 | <dependency> |
1、真实对象的接口:
1 | public interface SomeService { |
2、实现真实对象
1 | public class SomeServiceImpl implements SomeService { |
3、切面对象,用于给业务增加功能
1 | /** |
常用Pointcut表达式
拦截指定注解下的所有方法
1 "@annotation(com.zyz.advice.aspect.Log)") (拦截所有公共方法
1 "execution(public * *(..))") (拦截以set开头的所有方法
1 "execution(* set*(..))") (拦截类或接口中的所有方法
1 "execution(* com.zyz.service.xxxService.*(..))") (拦截包中定义的方法,不包含子包中的方法
1 "execution(* com.zyz.service.*.*(..))") (拦截包或者子包中定义的方法
1 "execution(* com.zyz.service..*.*(..))") (
4、添加配置文件,由spring创建需要的对象
1 |
|
5、测试
1 |
|
结果:
后置通知:
1 | /** |
环绕通知:
1 | /** |