装饰者模式,代理模式,AOP浅析
重写
继承,重写
使用场景
主要用于子类覆盖父类的方法
装饰者设计模式模式
如何使用
在构造方法中添加要装饰的对象
使用场景
一般应用于增加方法
不改变原来的功能
被装饰的类
class Dog{ public void eat(){ System.out.println("狗在吃骨头...."); } public void say(){ System.out.println("狗在汪汪汪的叫..."); } }
装饰的类
class ZHDog{ private Dog dog; public ZHDog(Dog dog){ this.dog = dog; } public void eat(){ dog.eat(); } public void say(){ dog.say(); } public void drink(){ System.out.println("狗喝.."); } }
代理设计模式
静态代理模式
优点
可以将功能型代码和业务逻辑分开
缺点
代码的重复并没有解决
接口
接口中包含需要代理的方法
实现接口的类
将代理的方法进行实现(真正需要实现的代码逻辑)
代理类实现
将实现接口的类,进行代理(对代码进行增强)
创建被代理者
对代码进行增强
需要实现的接口: interface MX
interface MX{ public void sing(); public void dance(); public void rap(); public void ball(); }
被代理者:ZJL
class ZJL implements MX{ @Override public void sing() { System.out.println("周杰伦在唱歌"); } @Override public void dance() { System.out.println("周杰伦在跳舞"); } @Override public void rap() { System.out.println("周杰伦双节棍"); } @Override public void ball() { System.out.println("周杰伦在斗牛"); } }
代理者:JJR
class JJR implements MX{ private ZJL zjl = new ZJL(); @Override public void sing() { // TODO Auto-generated method stub System.out.println("您是谁啊?"); System.out.println("记录一下"); zjl.sing(); System.out.println("结账"); } @Override public void dance() { System.out.println("您是谁啊?"); System.out.println("记录一下'"); zjl.dance(); System.out.println("结账"); } @Override public void rap() { // TODO Auto-generated method stub zjl.rap(); } @Override public void ball() { // TODO Auto-generated method stub zjl.ball(); } }
动态代理
java基于接口实现
代理者不是自己创建的类,而是被生成的对象
局限性
类中有接口中没有的方法,无法被代理
java动态代理的使用方法
/// 参数一:类加载器 应该和被代理者的加载器相同 /// 参数二:接口的数组 应该和被代理者的接口相同 // 参数三: 回调函数的接口 可以直接使用匿名内部类的形式 // 当代理者调用接口中的方法时,会先执行到回调函数中 /// 回调函数会拦截所有的代理者调用的接口方法 Object proxy = Proxy.newProxyInstance(loader, interfaces, new InvocationHandler() { @Override // proxy 代理者 // method 代理者的方法 // args 代理者的参数列表 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub // 返回方法执行后的返回值 return null; } })
基于java接口实现(举例)
package com.wiscom.demo; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Arrays; public class ProxyDemo { public static void main(String[] args) { // 被代理者 final CXK kk = new CXK(); MX proxy = (MX) Proxy.newProxyInstance(kk.getClass().getClassLoader(), kk.getClass().getInterfaces(), new InvocationHandler() { @Override // 参数一:代理者 // 参数二:代理者调用的方法 // 参数三:代理者调用方法的参数 // 返回值就是方法的返回值 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub System.out.println("方法拦截了吗?"); System.out.println(method.getName()); System.out.println(Arrays.toString(args)); // 调用method方法 Object obj = method.invoke(kk, args);// kk.sing(args) kk.dance(args) return obj; } }); // 通过动态代理生成的代理者调用明星的方法 proxy.sing(); proxy.dance(""); } } interface MX{ public void sing(); public void dance(String name); } class CXK implements MX{ @Override public void sing() { System.out.println("wait wait wait"); } @Override public void dance(String name) { System.out.println("跳舞~~~~"); } public void eat(){ System.out.println("吃饭......"); } }
cglib实现代理
cglib实现动态代理(第三方包)
包在spring-core中已包含
package com.wiscom.demo; import java.lang.reflect.Method; import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; public class Demo { public static void main(String[] args) { // 被代理者 final WYF ff = new WYF(); // 创建增强器 Enhancer en = new Enhancer(); // 可以提供接口 可以设置 可以不设置 // en.setInterfaces(ff.getClass().getInterfaces()); // 设置父类 en.setSuperclass(ff.getClass()); // 设置回调函数 en.setCallback(new MethodInterceptor() { @Override // 参数一:代理者 参数二:代理调用的方法 参数三:参数类型 public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { System.out.println(method.getName()); Object obj; if ("rap".equals(method.getName())){ obj = method.invoke(ff, args); System.out.println("你们来这里吃面很开心"); }else{ obj = method.invoke(ff, args); } return obj; } }); // 获取代理 WYF proxy = (WYF)en.create(); // 调用方法 proxy.rap(); proxy.dance(); } } class WYF{ public void rap(){ System.out.println("你看这个碗又大又圆"); } public void dance(){ System.out.println("跳舞..."); } }
AOP
连接点
controller中调用service中的方法
切入点
切入点=连接点+切入规则
基于切入规则选择出来的连接点
切面
狭义:spring拦截下的切入点
广义:一整套完整的aop代理机制
通知
切面中的方法
目标对象
最终需要调用的真正对象,也就是被代理的对象
com.wiscom.aspect.FirstAspect
package com.wiscom.aspect; import org.springframework.stereotype.Component; // 切面类 @Component public class FirstAspect { // 通知 public void before(){ System.out.println("开启事务"); System.out.println("开启日志"); System.out.println("权限设置"); } }
applicationContext
<aop:config> <!-- 配置切入点 --> <aop:pointcut expression="within(com.wiscom.service.UserServletImply)" id="pc01"/> <!-- 配置切面 --> <aop:aspect ref="firstAspect"> <!-- 配置通知 --> <aop:before method="before" pointcut-ref="pc01"/> </aop:aspect> </aop:config>
保存redis相关笔记