设计模式之代理模式实现原理,基于责任链模式构建企业级风控系统,基于装饰模式设计多级缓存,基于策略模式实现发送消息,基于观察者模式设计异步多渠道群发框架

发布于:2023-01-09 ⋅ 阅读:(761) ⋅ 点赞:(0)

1.什么是策略模式?
2.策略模式的应用场景
3.策略模式的实现方案有那些
4.基于工厂模式实现策略模式
5.基于数据库方式实现策略模式
6.站在架构师角度,设计多行为策略模式框架

设计模式的分类
创建型模式
工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式
适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式
行为模式
策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
彻底搞懂代理模式实现原理
什么是代理模式
代理模式主要对我们方法执行之前与之后实现增强
代理模式应用场景
1.日志的采集
2.权限控制
3.实现aop
4.Mybatis mapper
5.Spring的事务
6.全局捕获异常
7.Rpc远程调用接口
8.代理数据源
代理模式实现的原理
代理模式主要包含三个角色,即抽象主题角色(Subject)、委托类角色(被代理角色,Proxied)以及代理类角色(Proxy),如上图所示:

抽象主题角色:可以是接口,也可以是抽象类;
委托类角色:真实主题角色,业务逻辑的具体执行者;
代理类角色:内部含有对真实对象RealSubject的引用,负责对真实主题角色的调用,并在真实主题角色处理前后做预处理和后处理。

代理模式创建方式
静态代理
静态代理需要自己人工编写代理类代码
基于接口实现方式

public class OrderServiceProxy  implements  OrderService{
    private OrderService orderService;

    public OrderServiceProxy(OrderService orderService) {
        this.orderService = orderService;
    }

    public String addOrder(String userName, String userPwd) {
        System.out.println("使用静态代理类打印日志开始:userName:" + userName + "," + userPwd);
        String result = orderService.addOrder(userName, userPwd);
        System.out.println("使用静态代理类打印日志结束:userName:" + userName + "," + userPwd);
        return result;
    }
}

public interface OrderService {
    /**
     * 需要被代理的方法
     * @return
     */
     String addOrder(String userName,String userPwd);
}

public class Test001 {
    public static void main(String[] args) {
        OrderService orderService = new OrderServiceProxy(new OrderServiceImpl());
        orderService.addOrder("mayikt","123456");
    }
}

基于继承的实现方式
public class OrderServiceProxy  extends OrderServiceImpl {
    private OrderService orderService;

    public OrderServiceProxy(OrderService orderService) {
        this.orderService = orderService;
    }

    public String addOrder(String userName, String userPwd) {
        System.out.println("使用静态代理类打印日志开始:userName:" + userName + "," + userPwd);
        String result = super.addOrder(userName, userPwd);
        System.out.println("使用静态代理类打印日志结束:userName:" + userName + "," + userPwd);
        return result;
    }
}

动态代理与静态代理的区别

动态代理不需要写代理类对象,通过程序自动生成,而静态代理需要我们自己写代理类对象。

动态代理
动态代理是在实现阶段不用关心代理类,而在运行阶段才指定哪一个对象。
动态代理类的源码是在程序运行期间由JVM根据反射等机制动态的生成 。

Jdk动态代理
JDK动态代理的一般步骤如下:
1.创建被代理的接口和类;
2.实现InvocationHandler接口,对目标接口中声明的所有方法进行统一处理;
3.调用Proxy的静态方法,创建代理类并生成相应的代理对象;

实现原理:利用拦截器机制必须实现InvocationHandler接口中的invoke方法实现对
我们的目标方法增强。

public class JdkInvocationHandler implements InvocationHandler {
    /**
     * 目标对象
     */
    private Object target;

    public JdkInvocationHandler(Object target) {
        this.target = target;
    }

    /**
     * @param proxy  使用jdk程序生成的代理类
     * @param method 目标方法
     * @param args   方法需要传递的参数
     * @return
     */
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("使用Jdk动态代理打印日志开始" + args[0]);
        Object result = method.invoke(target, args);
        System.out.println("使用Jdk动态代理打印日志结束" + args[1]);
        return result;
    }

    /**
     * 生成代理类
     *
     * @param <T>
     * @return
     */
    public <T> T getProxy() {
        return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(), this);
    }

}


public class JdkInvocationHandler implements InvocationHandler {
    /**
     * 目标对象
     */
    private Object target;

    public JdkInvocationHandler(Object target) {
        this.target = target;
    }

    /**
     * @param proxy  使用jdk程序生成的代理类
     * @param method 目标方法
     * @param args 方法需要传递的参数
     * @return
     */
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("使用Jdk动态代理打印日志开始" + args[0]);
        Object result = method.invoke(target, args);
        System.out.println("使用Jdk动态代理打印日志结束" + args[1]);
        return result;
    }

    public <T> T getProxy() {
        return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(), this);
    }

}

JdkInvocationHandler jdkInvocationHandler = new JdkInvocationHandler(new OrderServiceImpl());
OrderServiceImpl orderService = jdkInvocationHandler.getProxy();
orderService.addOrder(“mayikt”, “meite”);

加上该代码:

1.获取代理的生成的class文件
System.getProperties().put(“sun.misc.ProxyGenerator.saveGeneratedFiles”, “true”);

2.使用反编译工具该Proxy0.class

注意:继承了Proxy类,实现了代理的接口,由于java不能多继承,这里已经继承了Proxy类了,不能再继承其他的类,所以JDK的动态代理不支持对实现类的代理,只支持接口的代理。

纯手写Jdk动态代理

思路分析:
1.定义InvocationHandler类 回调方法
2.使用java反射技术获取接口下所有的方法,拼接 P r o x y 0. j a v a 代码 3. 在将 Proxy0.java代码 3.在将 Proxy0.java代码3.在将Proxy0.java编译成class文件,读取到内存中

public class $Proxy0 implements com.mayikt.service.OrderService {

private MayiktJdkInvocationHandler h;
private static Method m3;

public $Proxy0(MayiktJdkInvocationHandler mayiktJdkInvocationHandler) {
    this.h = mayiktJdkInvocationHandler;
}

@Override
public String addOrder(String ver1, String var2) {
    try {
        return (String) h.invoke(this, m3, new Object[]{ver1, var2});
    } catch (RuntimeException | Error var4) {
        throw var4;
    } catch (Throwable var5) {
        throw new UndeclaredThrowableException(var5);
    }
}

static {
    try {
        m3 = Class.forName("com.mayikt.service.OrderService").getMethod("addOrder", Class.forName("java.lang.String"), Class.forName("java.lang.String"));
    } catch (NoSuchMethodException var2) {
        throw new NoSuchMethodError(var2.getMessage());
    } catch (ClassNotFoundException var3) {
        throw new NoClassDefFoundError(var3.getMessage());
    }
}

}

public class MyJdkInvocationHandler implements MayiktJdkInvocationHandler {
    /**
     * 目标对象
     */
    private Object target;

    public MyJdkInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("使用Jdk动态代理打印日志开始" + args[0]);
        Object result = method.invoke(target, args);
        System.out.println("使用Jdk动态代理打印日志结束" + args[1]);
        return result;
    }
    public <T> T getProxy() {
        return (T) new $Proxy0(this);
    }
}

MyJdkInvocationHandler myJdkInvocationHandler = new MyJdkInvocationHandler(new OrderServiceImpl());
OrderService orderService = myJdkInvocationHandler.getProxy();
orderService.addOrder(“mayikt”, “meite”);

public class MyProxy {
    private static String rt = "\r\t";

    public static Object newProxyInstance(JavaClassLoader classLoader, Class classInfo, MayiktInvocationHandler mayiktInvocationHandler) {
        try {
            // 1.拼接java代理代理源代码
            Method[] methods = classInfo.getMethods();
            String proxyClass = "package com.mayikt.service;" + rt
                    + "import java.lang.reflect.Method;" + rt
                    + "import com.mayikt.service.proxy.MayiktInvocationHandler;" + rt
                    + "import java.lang.reflect.UndeclaredThrowableException;" + rt
                    + "public class $Proxy0 implements " + classInfo.getName() + "{" + rt
                    + "MayiktInvocationHandler h;" + rt
                    + "public $Proxy0(MayiktInvocationHandler h)" + "{" + rt
                    + "this.h= h;" + rt + "}"
                    + getMethodString(methods, classInfo) + rt + "}";
            // 2.将该源代码写入到本地文件中
            String filename = "d:/code/$Proxy0.java";
            File f = new File(filename);
            FileWriter fw = new FileWriter(f);
            fw.write(proxyClass);
            fw.flush();
            fw.close();
            // 3.编译为class文件
            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
            StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null);
            Iterable units = fileMgr.getJavaFileObjects(filename);
            JavaCompiler.CompilationTask t = compiler.getTask(null, fileMgr, null, null, null, units);
            t.call();
            fileMgr.close();
            // 4.将class文件加入到内存中
            Class proxy0Class = classLoader.findClass("$Proxy0");
            //5.使用java反射机制给函数中赋值
            Constructor m = proxy0Class.getConstructor(MayiktInvocationHandler.class);
            Object object = m.newInstance(mayiktInvocationHandler);
            return object;
        } catch (Exception e) {
            return null;
        }
    }

    public static String getMethodString(Method[] methods, Class intf) {
        String proxyMe = "";

        for (Method method : methods) {
            Class<?>[] parameterTypes = method.getParameterTypes();
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < parameterTypes.length; i++) {
                sb.append(parameterTypes[i].getName() + " ver" + (i + 1));
                if (i < parameterTypes.length - 1) {
                    sb.append(" ,");
                }
            }
            String parameterStr = sb.toString();
            proxyMe = "public " + method.getReturnType().getName() + " " + method.getName() + " ( " + parameterStr + " ) { " +
                    "try {   Method m3 = Class.forName(\"com.mayikt.service.OrderService\").getMethod(\"addOrder\", Class.forName(\"java.lang.String\"), Class.forName(\"java.lang.String\"));" +
                    "return (String) h.invoke(this, m3, new Object[]{ver1, ver2}); } catch (RuntimeException | Error var4) {  throw var4;  } catch (Throwable var5) {   throw new UndeclaredThrowableException(var5); } " +
                    "" +
                    " } ";

        }
        return proxyMe;
    }

    public static void main(String[] args) {
        newProxyInstance(null, OrderService.class, null);
    }
}

public class JavaClassLoader extends ClassLoader {

    private File classPathFile;

    public JavaClassLoader(){
//        String classPath=JavaClassLoader.class.getResource("").getPath();
        String classPath="D:\\code";
        this.classPathFile=new File(classPath);
    }

    @Override
    public Class<?> findClass(String name) throws ClassNotFoundException {
        String className= JavaClassLoader.class.getPackage().getName()+"."+name;
        if(classPathFile!=null){
          File classFile=new File(classPathFile,name.replaceAll("\\.","/")+".class");
          if(classFile.exists()){
              FileInputStream in=null;
              ByteArrayOutputStream out=null;
              try {
                  in=new FileInputStream(classFile);
                  out=new ByteArrayOutputStream();
                  byte[] buff=new byte[1024];
                  int len;
                  while ((len=in.read(buff))!=-1){
                     out.write(buff,0,len);
                  }
                  return defineClass(className,out.toByteArray(),0,out.size());
              }catch (Exception e){
                  e.printStackTrace();
              }finally {
                  if(in!=null){
                      try {
                          in.close();
                      } catch (IOException e) {
                          e.printStackTrace();
                      }
                  }
                  if(out!=null){
                      try {
                          out.close();
                      } catch (IOException e) {
                          e.printStackTrace();
                      }
                  }
              }
          }
        }
        return null;
    }
}

public class MyJdkInvocationHandler implements MayiktJdkInvocationHandler {
    /**
     * 目标对象
     */
    private Object target;

    public MyJdkInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("使用Jdk动态代理打印日志开始" + args[0]);
        Object result = method.invoke(target, args);
        System.out.println("使用Jdk动态代理打印日志结束" + args[1]);
        return result;
    }


    public <T> T getProxy() {
        return (T) MyProxy.newProxyInstance(new JavaClassLoader(), target.getClass().getInterfaces()[0], this);
    }
}

CGLIB动态代理
利用asm字节码技术,生成子类实现对目标方法实现增强
实现方式
Maven依赖


cglib
cglib
3.2.12

核心代码

public class CglibMethodInterceptor implements MethodInterceptor {
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("<<<<<日志收集开始...>>>>>>>");
        Object reuslt = proxy.invokeSuper(obj, args);
        System.out.println("<<<<<日志收集结束...>>>>>>>");
        return reuslt;
    }
}


System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\code");
CglibMethodInterceptor cglibMethodInterceptor = new CglibMethodInterceptor();
Enhancer enhancer = new Enhancer();
// 设置代理类的付类
enhancer.setSuperclass(MemberServiceImpl.class);
// 设置回调对象
enhancer.setCallback(cglibMethodInterceptor);
// 创建代理对象
MemberServiceImpl orderServiceImpl = (MemberServiceImpl) enhancer.create();
orderServiceImpl.getMember();

Cglib动态代理底层源码分析
Cglib依赖于ASM字节码技术,直接生成class文件,在采用类加载器读取到程序中,
使用fastclass对被代理类的方法建立索引文件不需要依赖于反射查找到目标方法,所以效率比Jdk动态代理要高。

public class OrderServiceImpl$$EnhancerByCGLIB$$1dd3a71c extends OrderServiceImpl {

    static void CGLIB$STATICHOOK1() throws ClassNotFoundException {
        Method amethod[];
        Method amethod1[];
        CGLIB$THREAD_CALLBACKS = new ThreadLocal();
        CGLIB$emptyArgs = new Object[0];
        Class class1 = Class.forName("com.mayikt.service.impl.OrderServiceImpl$$EnhancerByCGLIB$$1dd3a71c");
        Class class2;
        amethod = ReflectUtils.findMethods(new String[]{
                "addOrder", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"
        }, (class2 = Class.forName("com.mayikt.service.impl.OrderServiceImpl")).getDeclaredMethods());
        Method[] _tmp = amethod;
        CGLIB$addOrder$0$Method = amethod[0];
        CGLIB$addOrder$0$Proxy = MethodProxy.create(class2, class1, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", "addOrder", "CGLIB$addOrder$0");
        amethod1 = ReflectUtils.findMethods(new String[]{
                "equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"
        }, (class2 = Class.forName("java.lang.Object")).getDeclaredMethods());
        Method[] _tmp1 = amethod1;
        CGLIB$equals$1$Method = amethod1[0];
        CGLIB$equals$1$Proxy = MethodProxy.create(class2, class1, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$1");
        CGLIB$toString$2$Method = amethod1[1];
        CGLIB$toString$2$Proxy = MethodProxy.create(class2, class1, "()Ljava/lang/String;", "toString", "CGLIB$toString$2");
        CGLIB$hashCode$3$Method = amethod1[2];
        CGLIB$hashCode$3$Proxy = MethodProxy.create(class2, class1, "()I", "hashCode", "CGLIB$hashCode$3");
        CGLIB$clone$4$Method = amethod1[3];
        CGLIB$clone$4$Proxy = MethodProxy.create(class2, class1, "()Ljava/lang/Object;", "clone", "CGLIB$clone$4");
    }

    final String CGLIB$addOrder$0(String s, String s1) {
        return super.addOrder(s, s1);
    }


    final boolean CGLIB$equals$1(Object obj) {
        return super.equals(obj);
    }


    final String CGLIB$toString$2() {
        return super.toString();
    }


    final int CGLIB$hashCode$3() {
        return super.hashCode();
    }


    public static void CGLIB$SET_THREAD_CALLBACKS(Callback acallback[]) {
        CGLIB$THREAD_CALLBACKS.set(acallback);
    }

    public final String addOrder(String paramString1, String paramString2) {
        MethodInterceptor tmp4_1 = this.CGLIB$CALLBACK_0;
        if (tmp4_1 == null) {

            CGLIB$BIND_CALLBACKS(this);
        }
        try {
            MethodInterceptor tmp17_14 = this.CGLIB$CALLBACK_0;
            if (tmp17_14 != null) {
                return (String) tmp17_14.intercept(this, CGLIB$addOrder$0$Method, new Object[]{paramString1, paramString2}, CGLIB$addOrder$0$Proxy);
            }
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return super.addOrder(paramString1, paramString2);
    }


    public Object newInstance(Callback acallback[]) {
        CGLIB$SET_THREAD_CALLBACKS(acallback);
        CGLIB$SET_THREAD_CALLBACKS(null);
        return new OrderServiceImpl$$EnhancerByCGLIB$$1dd3a71c();
    }

    public Object newInstance(Callback callback) {
        CGLIB$SET_THREAD_CALLBACKS(new Callback[]{
                callback
        });
        CGLIB$SET_THREAD_CALLBACKS(null);
        return new OrderServiceImpl$$EnhancerByCGLIB$$1dd3a71c();
    }


    public void setCallback(int i, Callback callback) {
        switch (i) {
            case 0: // '\0'
                CGLIB$CALLBACK_0 = (MethodInterceptor) callback;
                break;
        }
    }


    private boolean CGLIB$BOUND;
    public static Object CGLIB$FACTORY_DATA;
    private static ThreadLocal CGLIB$THREAD_CALLBACKS = null;
    private static final Callback CGLIB$STATIC_CALLBACKS[] = null;
    private MethodInterceptor CGLIB$CALLBACK_0;
    private static Object CGLIB$CALLBACK_FILTER;
    private static Method CGLIB$addOrder$0$Method = null;
    private static MethodProxy CGLIB$addOrder$0$Proxy = null;
    private static Object[] CGLIB$emptyArgs = null;
    private static Method CGLIB$equals$1$Method = null;
    private static MethodProxy CGLIB$equals$1$Proxy = null;
    private static Method CGLIB$toString$2$Method = null;
    private static MethodProxy CGLIB$toString$2$Proxy = null;
    private static Method CGLIB$hashCode$3$Method = null;
    private static MethodProxy CGLIB$hashCode$3$Proxy = null;
    private static Method CGLIB$clone$4$Method = null;
    private static MethodProxy CGLIB$clone$4$Proxy = null;

    static {
        try {
            CGLIB$STATICHOOK1();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    public OrderServiceImpl$$EnhancerByCGLIB$$1dd3a71c() {
        CGLIB$BIND_CALLBACKS(this);
    }

    private void CGLIB$BIND_CALLBACKS(OrderServiceImpl$$EnhancerByCGLIB$$1dd3a71c orderServiceImpl$$EnhancerByCGLIB$$1dd3a71c) {
    }
}

FastClass机制
public class MayiktFastclass {

/**
 * 根据索引查找到目标方法
 *
 * @param index
 * @param obj
 * @param args
 * @return
 */
public static Object invoke(int index, Object obj, Object[] args) {
    OrderServiceImpl orderService = (OrderServiceImpl) obj;
    switch (index) {
        case 1:
            return orderService.addOrder(String.valueOf(args[0]), String.valueOf(args[1]));
    }
    return null;
}

/**
 * 根据签名简历索引文件
 *
 * @param sign
 * @return
 */
public static int getIndex(String sign) {
    switch (sign.hashCode()) {
        case 1763340254:
            return 1;
        case 20:
            return 2;
    }
    return -1;
}

public static void main(String[] args) {
    System.out.println("addOrder()String,String".hashCode());
    Object result = invoke(getIndex("addOrder()String,String"), new OrderServiceImpl(), new String[]{"mayikt", "meite"});
}

}

Jdk与Cglib动态代理的区别
1.Jdk动态代理利用反射技术生成匿名的代理类走InvokeHandler回调方法实现增强,同时也是一种基于接口的方式实现代理。
2.Cglib动态代理利用asm字节码技术生成一个子类覆盖其中的方法实现增强,同时采用fastClass机制对整个代理类建立索引比反射效率要高
3.在Spring中如果需要被代理的对象如果实现了接口采用Jdk动态代理,没有实现接口则使用Cglib动态代理。

Springboot @async失效之谜
@async异步主要 在方法加上该注解可以实现异步的效果

注意:
1.必须将异步回调的方法单独使用一个类调用或者从容器中获取对象,如果在没有调用代理类情况下
@async否则会失效。
2.如果SpringMVC控制类实现了接口,在该类中加上个了@Async会导致将该对象注入到
SpringMVC容器中 AbstractHandlerMethodMapping

@RestController
@Slf4j
public class MemberServiceImpl {
    @Autowired
    private MemberServiceManage memberServiceManage;

    @GetMapping("/addUser")
    public String addUser() {
        log.info(">>>流程1");
        memberServiceManage.addUserLog();
        log.info(">>>流程3");
        return "success";
    }
}

@Component
public class SpringUtils implements ApplicationContextAware {


    private static ApplicationContext applicationContext = null;

    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }


    public static <T> T getBean(String beanId) {
        return (T) applicationContext.getBean(beanId);
    }

    public static <T> T getBean(Class<T> requiredType) {
        return (T) applicationContext.getBean(requiredType);
    }


    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringUtils.applicationContext = applicationContext;
    }

}

4.方法名称必须要是公有的
基于Aop手写异步注解框架

自定义注解

Java注解是Jdk1.5推出一个重大特性 可以标记在类、方法、属性上面

内置注解:
1.@Override - 检查该方法是否是重写方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误。
2.@Deprecated - 标记过时方法。如果使用该方法,会报编译警告。

元注解:
@Retention - 标识这个注解怎 么保存,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问。
@Documented - 标记这些注解是否包含在用户文档中。
@Target - 标记这个注解应该是哪种 Java 成员。
@Inherited - 标记这个注解是继承于哪个注解类(默认 注解并没有继承于任何子类)

基于Jdk动态代理手写异步注解

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExtAsync {
}

public class JdkInvocationHandler implements InvocationHandler {
    /**
     * 目标对象
     */
    private Object target;
    private ExecutorService executorService;

    public JdkInvocationHandler(Object target) {
        this.target = target;
        executorService = Executors.newFixedThreadPool(10);
    }

    public Object invoke(Object proxy, final Method method, final Object[] args) throws Throwable {
        // 执行我们的目标方法
//        ExtAsync extAsync = method.getDeclaredAnnotation(ExtAsync.class);
        // 获取对应子类上是否有加上 @注解ExtAsync
        Method methodImpl = target.getClass().getMethod(method.getName(), method.getParameterTypes());
        ExtAsync extAsync = methodImpl.getDeclaredAnnotation(ExtAsync.class);
        Object result = null;


        if (extAsync != null) {
            // 则开启线程执行目标方法
            try {
                executorService.execute(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            method.invoke(target, args);
                            return;
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        } catch (InvocationTargetException e) {
                            e.printStackTrace();
                        }
                    }
                });

            } catch (Exception e) {

            }
        } else {
            result = method.invoke(target, args);
        }
        return result;
    }

    /**
     * 生成代理类
     *
     * @param <T>
     * @return
     */
    public <T> T getProxy() {
        return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(), this);
    }
}

OrderServiceImpl orderServiceImpl = new OrderServiceImpl();
JdkInvocationHandler jdkInvocationHandler = new JdkInvocationHandler(orderServiceImpl);
OrderService orderService = jdkInvocationHandler.getProxy();
orderServiceImpl.setProxy(orderService);
orderService.addOrder();

基于SpringAop动态代理手写异步注解

@Component
@Slf4j
@Aspect
public class ExtAsyncAop {

    private ExecutorService executorService;

    public ExtAsyncAop() {
        executorService = Executors.newFixedThreadPool(2);
    }

    @Around(value = "@annotation(com.mayikt.service.ext.ExtAsync)")
    public void doBefore(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println(">>>开始拦截到注解");
        executorService.execute(new Runnable() {
            @SneakyThrows
            @Override
            public void run() {
                joinPoint.proceed();
            }
        });


    }
}

基于装饰模式设计多级缓存

回顾多级缓存基本概念

在实际开发项目,为了减少数据库的访问压力,我们都会将数据缓存到内存中
比如:Redis(分布式缓存)、EHCHE(JVM内置缓存).
例如在早起中,项目比较小可能不会使用Redis做为缓存,使用JVM内置的缓存框架,
项目比较大的时候开始采用Redis分布式缓存框架,这时候需要设计一级与二级缓存。

装饰模式基本的概念
不改变原有代码的基础之上,新增附加功能

装饰模式应用场景
多级缓存设计、mybatis中一级与二级缓存、IO流
装饰者模式定义
(1)抽象组件:定义一个抽象接口,来规范准备附加功能的类
(2)具体组件:将要被附加功能的类,实现抽象构件角色接口
(3)抽象装饰者:持有对具体构件角色的引用并定义与抽象构件角色一致的接口
(4)具体装饰:实现抽象装饰者角色,负责对具体构件添加额外功能。

基于Map手写Jvm内置缓存

public class JvmMapCacheUtils {

    private static HashMap<String, String> cacheMap = new HashMap<String, String>();

    public static void putEntity(String key, Object object) {
        cacheMap.put(key, JSONObject.toJSONString(object));
    }

    public static <T> T getEntity(String key, Class<T> t) {
        String json = cacheMap.get(key);
        JSONObject jsonObject = JSONObject.parseObject(json);
        return JSONObject.parseObject(json, t);
    }
}

简单手写一级与二级缓存效果

@RequestMapping("/getUser")
public UserEntity getUser(Integer userId) {
    //1.先查询Jvm内置缓存是否有数据
    String key = "getUser()";
    UserEntity redisUser = redisUtils.getEntity(key, UserEntity.class);
    if (redisUser != null) {
        return redisUser;
    }
    log.info(">>开始查询一级缓存<<<");
    UserEntity jvmCacheUserEntity = JvmMapCacheUtils.getEntity(key, UserEntity.class);
    if (jvmCacheUserEntity != null) {
        // 直接返回缓存对象 并且将该缓存数据缓存到Redis中
        redisUtils.putEntity(key, jvmCacheUserEntity);
        return jvmCacheUserEntity;
    }
    // 2.直接查询数据库db
    log.info(">>一级缓存中没有数据,查询二级缓存<<<");
    UserEntity dbUserEntity = userMapper.findByUser(userId);
    if (dbUserEntity == null) {
        log.info(">>数据库DB未查询到数据<<<");
        return null;
    }
    // 将db的数据缓存到一级缓存中
    JvmMapCacheUtils.putEntity(key, dbUserEntity);
    return dbUserEntity;
}

基于装饰模式实现多级缓存优化
一级缓存

public interface ComponentCache {
    <T> T getEntity(String key, Class<T> T, ProceedingJoinPoint joinPoint);
}
@Component
public class JvmComponentCache implements ComponentCache {
//
//    @Autowired
//    private UserMapper userMapper;

    @Override
    public <T> T getEntity(String key, Class<T> t, ProceedingJoinPoint joinPoint) {
        T twoEntity = JvmMapCacheUtils.getEntity(key, t);
        if (twoEntity != null) {
            return twoEntity;
        }
//        // 查询数据库db
//        UserEntity dbUser = userMapper.findByUser(1);
//        if (dbUser == null) {
//            return null;
//        }
        try {
            Object dbProceed = joinPoint.proceed();
            if (dbProceed == null) {
                return null;
            }
            JvmMapCacheUtils.putEntity(key, dbProceed);
            return (T) dbProceed;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            return null;
        }

    }

}

新增二级缓存

public interface AbstractDecorate extends  ComponentCache {
}
@Component
public class RedisDecorate implements AbstractDecorate {
    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private JvmComponentCache jvmComponentCache;


    @Override
    public <T> T getEntity(String key, Class<T> t, ProceedingJoinPoint joinPoint) {
        // 查询我们的二级缓存
        T twoEntity = redisUtils.getEntity(key, t);
        if (twoEntity != null) {
            return twoEntity;
        }
        //  如果二级缓存没有查询成功则查询一级缓存
        T jvmEntity = jvmComponentCache.getEntity(key, t,joinPoint);
        if (jvmEntity == null) {
            return null;
        }
        // 一级缓存如果有数据的情况则,则将一级缓存数据放入到二级缓存中
        redisUtils.putEntity(key, jvmEntity);
        return jvmEntity;
    }

}

使用一级与二级缓存

@Component
public class MayikCache {
    @Autowired
    private RedisDecorate redisDecorate;

    public <T> T getCache(String key, Class<T> t, ProceedingJoinPoint joinPoint) {
        return redisDecorate.getEntity(key, t,joinPoint);
    }
}

Aop与自定义注解

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExtMeiteCache {
}
@Aspect
@Component
@Slf4j
public class ExtAsyncAop {
    @Autowired
    private MayikCache mayikCache;

    @Around(value = "@annotation(com.mayikt.aop.ExtMeiteCache)")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method targetMethod = methodSignature.getMethod();
        String cacheKey = targetMethod.getName() + "," + Arrays.toString(targetMethod.getParameterTypes());
        log.info(">>cacheKey:" + cacheKey);
        return mayikCache.getCache(cacheKey, targetMethod.getReturnType(), joinPoint);
    }
}

装饰与代理区别
装饰模式对我们的装饰对象实现增强,而代理模式及对我们目标对象实现增强。

基于观察者模式设计异步多渠道群发框架
观察者模式基本概念
一个对象状态改变,通知给其他所有的对象
观察者模式的应用场景
Zk的事件监听、分布式配置中心刷新配置文件、业务中群发不同渠道消息

观察者模式的类图

简单的实现ObServer观察者
定义ObServer接口

public interface MayiktObServer {
    void sendMsg(JSONObject jsonObject);
}
@Component
public class EmailServer implements MayiktObServer {

    public void sendMsg(JSONObject jsonObject) {
        System.out.println(Thread.currentThread().getName() + "2.短信观察者监听");
    }
}
@Component
public class SmsObServer implements MayiktObServer {
    public void sendMsg(JSONObject jsonObject) {
        System.out.println(Thread.currentThread().getName()+"使用观察者监听短信");
    }
}

主题通知所有观察者

@Component
public class MayiktSmsSubject {
    private ExecutorService executorService;

    private List<MayiktObServer> listObServer = new ArrayList<MayiktObServer>();

    public MayiktSmsSubject() {
        executorService = Executors.newFixedThreadPool(10);
    }

    public void addObServer(MayiktObServer obServer) {
        listObServer.add(obServer);
    }

    public void deleteObServer(MayiktObServer obServer) {
        listObServer.remove(obServer);
    }

    public void notifyObServer(final JSONObject jsonObject) {
        for (final MayiktObServer obServer : listObServer) {
            executorService.execute(new Runnable() {
                public void run() {
                    obServer.sendMsg(jsonObject);
                }
            });

        }
    }

}

项目启动注册观察者

@Component
public class StartService implements ApplicationRunner {

    @Autowired
    private MayiktSmsSubject mayiktSmsSubject;
    @Autowired
    private EmailServer emailServer;
    @Autowired
    private EmailServer smsObServer;
    @Override
    public void run(ApplicationArguments args) throws Exception {
        mayiktSmsSubject.addObServer(emailServer);
        mayiktSmsSubject.addObServer(smsObServer);
    }
}


    @Autowired
    private MayiktSmsSubject mayiktSmsSubject;

    @RequestMapping("/addOrder")
    public String addOrder() {
        log.info("1.调用数据库下单订单代码:");
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("sms", "1865891111");
        jsonObject.put("email", "644064779@qq.com");
//        log.info("2.发送短信代码");
//        log.info("3.发送邮件代码");
        mayiktSmsSubject.notifyObServer(jsonObject);
        return "success";
    }

实现自动化注册

@Component
public class StartService implements ApplicationRunner, ApplicationContextAware {
    @Autowired
    private SMSObServer smsObServer;
    @Autowired
    private EmailObServer emailObServer;
    @Autowired
    private MayiktSubject mayiktSubject;

    private ApplicationContext applicationContext;

    /**
     * 当我们的SpringBoot启动成功的时候,注册我们的SMSObServer
     *
     * @param args
     * @throws Exception
     */
    @Override
    public void run(ApplicationArguments args) throws Exception {
//        mayiktSubject.addObServer(smsObServer);
//        mayiktSubject.addObServer(emailObServer);
        //根据接口类型返回相应的所有bean
        Map<String, ObServer> map = applicationContext.getBeansOfType(ObServer.class);
        for (String key : map.keySet()) {
            mayiktSubject.addObServer(SpringUtils.getBean(key));
        }
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {

        this.applicationContext = applicationContext;
    }
}

基于Spring事件通知实现
定义消息实体类

public class UserMessageEntity extends ApplicationEvent {
    private String email;
    private String phone;
    private String userId;

    /**
     * Create a new ApplicationEvent.
     *
     * @param source the object on which the event initially occurred (never {@code null})
     */
    public UserMessageEntity(Object source) {
        super(source);
    }

    public UserMessageEntity(Object source, String email, String phone) {
        super(source);
        this.email = email;
        this.phone = phone;
    }

    @Override
    public String toString() {
        return "email:" + email + ",phone:" + phone;
    }
}

定义事件通知

@Component
public class EmailListener implements ApplicationListener<UserMessageEntity> {

    @Override
    public void onApplicationEvent(UserMessageEntity event) {
        System.out.println("eamil:"+event.toString());
    }
}
@Component
public class SmsListener implements ApplicationListener<UserMessageEntity> {

    @Override
    public void onApplicationEvent(UserMessageEntity event) {
        System.out.println("sms:" + event.toString());
    }

}



@Autowired
private ApplicationEventPublisher applicationEventPublisher;
@RequestMapping("/addOrder2")
public String addOrder2() {
    log.info("1.调用数据库下单订单代码:" + mayiktSmsSubject);
    UserMessageEntity messageEntity = new UserMessageEntity(this, "644064779@qq.com", "1865891111");
    applicationEventPublisher.publishEvent(messageEntity);
    return "success";
}

深入研究单例底层实现原理

单例基本概念
在当前Jvm中只会有一个该实例对象

单例应用场景
1.项目中定义的配置文件
2.Servlet对象默认就是单例
3.线程池、数据库连接池
4.Spring中Bean对象默认就是单例
5.实现网站计数器
6.Jvm内置缓存框架(定义单例HashMap)
7.定义枚举常量信息

单例优缺点

优点:能够节约当前堆内存,不需要频繁New对象,能够快速访问。
缺点:当多个线程访问同一个单例对象的时候可能会存在线程安全问题。
单例的(10种)写法

懒汉式线程不安全

public class Singleton01 {
    private static Singleton01 singleton01 = null;

    /**
     * 私有构造函数
     */
    private Singleton01() {

    }

    /**
     * 懒汉式 线程不安全
     *
     * @return
     */
    public static Singleton01 getInstance() {
        if (singleton01 == null) {
            singleton01 = new Singleton01();
        }
        return singleton01;
    }

    public static void main(String[] args) {
        Singleton01 instance1 = Singleton01.getInstance();
        Singleton01 instance2 = Singleton01.getInstance();
        System.out.println(instance1 == instance2);
    }

}
懒汉式:当真正需要获取对象的时候,才去创建该单例对象,该写法存在线程问题
懒汉式线程安全
public class Singleton02 {
    private static Singleton02 singleton02 = null;

    /**
     * 懒汉式线程安全 已经创建对象,获取该单例对象的时候还需要上锁效率比较低
     *
     * @return
     */
    public static synchronized Singleton02 getInstance() {
        if (singleton02 == null) {
            singleton02 = new Singleton02();
        }
        return singleton02;
    }

    public static void main(String[] args) {
        Singleton02 instance1 = Singleton02.getInstance();
        Singleton02 instance2 = Singleton02.getInstance();
        System.out.println(instance2 == instance1);
    }
}


该写法能够保证线程安全问题,获取该单例对象的时候效率非常低
懒汉式双重检验锁
public class Singleton03 {
    private static Singleton03 singleton03;

    public static Singleton03 getInstance() {
        // 第一次检查
        if (singleton03 == null) {
            //第二次检查
            synchronized (Singleton03.class) {
                if (singleton03 == null) {
                    singleton03 = new Singleton03();
                }
            }
        }
        return singleton03;
    }

    public static void main(String[] args) {
        Singleton03 instance1 = Singleton03.getInstance();
        Singleton03 instance2 = Singleton03.getInstance();
        System.out.println(instance1==instance2);
    }
}


能够保证线程安全,只会创建该单例对象的时候上锁,获取该该单例对象不会上锁,效率比较高。

饿汉式(私有)
public class Singleton04 {
    /**
     * 提前创建单例对象,优点先天性 保证线程安全,比较占用内存
     */
    public static final Singleton04 singleton04 = new Singleton04();

    private Singleton04() {

    }

    private static Singleton04 getInstance() {
        return singleton04;
    }

    public static void main(String[] args) {
        Singleton04 instance1 = Singleton04.getInstance();
        Singleton04 instance2 = Singleton04.getInstance();
        System.out.println(instance1 == instance2);
    }
}

饿汉式(公有)
public class Singleton04 {
    /**
     * 提前创建单例对象,优点先天性 保证线程安全,比较占用内存
     */
    public static final Singleton04 singleton04 = new Singleton04();

    private Singleton04() {

    }

    private static Singleton04 getInstance() {
        return singleton04;
    }

    public static void main(String[] args) {
        Singleton04 instance1 = Singleton04.singleton04;
        Singleton04 instance2 = Singleton04.singleton04;
        System.out.println(instance1 == instance2);
    }
}

静态代码块
public class Singleton05 {
    private static Singleton05 singleton05;

    static {
        singleton05 = new Singleton05();
    }

    public static Singleton05 getInstance() {
        return singleton05;
    }

    public static void main(String[] args) {
        Singleton05 instance1 = Singleton05.getInstance();
        Singleton05 instance2 = Singleton05.getInstance();
        System.out.println(instance1 == instance2);
    }
}


静态内部类
public class Singleton06 {
    private Singleton06() {
        System.out.println(">>>Singleton06");
    }

    private static class SingletonHolder {
        private static final Singleton06 singleton06 = new Singleton06();
    }

    public static final Singleton06 getInstance() {
        return SingletonHolder.singleton06;
    }

    public static void main(String[] args) {
        Singleton06 instance1 = Singleton06.getInstance();
        Singleton06 instance2 = Singleton06.getInstance();
        System.out.println(instance1==instance2);
    }
}

枚举实现单例子
public enum Singleton07 {

INSTANCE;

public void getInstance() {
    System.out.println("<<<getInstance>>>");
}

}

枚举最安全,不可以被反射也不能被序列化 破解
多少种方式可以创建对象
1.直接new对象
2.采用克隆对象
3.使用反射创建对象
4.序列化与反序列化

如何单例被破解
如何防止被反射破解

private Singleton01() throws Exception {
    if (singleton01 != null) {
        throw new Exception("该对象已经创建");
    }
    System.out.println("无参构造函数");
}

Class<?> aClass = Class.forName("com.mayikt.Singleton01");
Constructor<?> constructor = aClass.getDeclaredConstructor();
constructor.setAccessible(true);
Singleton01 instance02 = Singleton01.getInstance();
Singleton01 singleton01 = (Singleton01) constructor.newInstance();
System.out.println(singleton01==instance02);

如何防止序列化破解

序列化概念:将对象转换成二进制的形式直接存放在本地
反序列化概念:从硬盘读取二进制变为对象


// 1.将对象序列化存入到本地文件中
FileOutputStream fos = new FileOutputStream("d:/code/a.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
Singleton04 singleton1 = Singleton04.singleton04;
oos.writeObject(singleton1);
oos.close();
fos.close();
//2.从硬盘中反序列化对象到内存中
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("d:/code/a.txt"));
Singleton04 singleton2 = (Singleton04) ois.readObject();
System.out.println(singleton1);
System.out.println(singleton2);
public class Singleton04 implements Serializable {
    /**
     * 提前创建单例对象,优点先天性 保证线程安全,比较占用内存
     */
    public static final Singleton04 singleton04 = new Singleton04();

    private Singleton04() {
        System.out.println("Singleton04");
    }

    private static Singleton04 getInstance() {
        return singleton04;
    }

    public static void main(String[] args) {
        Singleton04 instance1 = Singleton04.singleton04;
        Singleton04 instance2 = Singleton04.singleton04;
        System.out.println(instance1 == instance2);
    }
}

重写该方法 指定返回的对象 防止序列化破解

private Object readResolve() throws ObjectStreamException {
    return singleton04;
}

注意:如果该类是Serializable类型的 则调用它第一个非Serializable父类的无参构造函数初始化该对象该对象

如何反射是否可以破解单例

不可以被反射 也不可以被序列化破解

//         1.将对象序列化存入到本地文件中
        FileOutputStream fos = new FileOutputStream("d:/code/a.txt");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        Singleton07 singleton1 = Singleton07.INSTANCE;
        oos.writeObject(singleton1);
        oos.close();
        fos.close();
        //2.从硬盘中反序列化对象到内存中
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("d:/code/a.txt"));
        Singleton07 singleton2 = (Singleton07) ois.readObject();
        System.out.println(singleton1==singleton2);

基于责任链实现权限框架

责任链基本概念

客户端发出一个请求,链上的对象都有机会来处理这一请求,而客户端不需要知道谁是具体的处理对象。这样就实现了请求者和接受者之间的解耦,并且在客户端可以实现动态的组合职责链。使编程更有灵活性。

定义:使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。其过程实际上是一个递归调用。

要点主要是:
 1、有多个对象共同对一个任务进行处理。
2、这些对象使用链式存储结构,形成一个链,每个对象知道自己的下一个对象。
3、一个对象对任务进行处理,可以添加一些操作后将对象传递个下一个任务。也可以在此对象上结束任务的处理,并结束任务。
4、客户端负责组装链式结构,但是客户端不需要关心最终是谁来处理了任务。
多个对象指的是什么意思?
责任链模式优缺点
优点:
职责链模式的最主要功能就是:动态组合,请求者和接受者解耦。
请求者和接受者松散耦合:请求者不需要知道接受者,也不需要知道如何处理。每个职责对象只负责自己的职责范围,其他的交给后继者。各个组件间完全解耦。
动态组合职责:职责链模式会把功能分散到单独的职责对象中,然后在使用时动态的组合形成链,从而可以灵活的分配职责对象,也可以灵活的添加改变对象职责。

缺点:
产生很多细粒度的对象:因为功能处理都分散到了单独的职责对象中,每个对象功能单一,要把整个流程处理完,需要很多的职责对象,会产生大量的细粒度职责对象。
不一定能处理:每个职责对象都只负责自己的部分,这样就可以出现某个请求,即使把整个链走完,都没有职责对象处理它。这就需要提供默认处理,并且注意构造链的有效性。
责任链模式类结构图

1.抽象处理者(Handler)角色:定义出一个处理请求的接口。如果需要,接口可以定义 出一个方法以设定和返回对下家的引用。这个角色通常由一个Java抽象类或者Java接口实现。上图中Handler类的聚合关系给出了具体子类对下家的引用,抽象方法handleRequest()规范了子类处理请求的操作。
 2.具体处理者(ConcreteHandler)角色:具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家

责任链模式应用场景
1.多条件流程判断 权限控制
2.ERP系统 流程审批 总经理、人事经理、项目经理
3.Java过滤器的底层实现Filter
4.风控系统 失信名单→信用卡是否逾期→蚂蚁信用积分650
比如:在Java过滤器中客户端发送请求到服务器端,过滤会经过参数过滤、session过滤、表单过滤、隐藏过滤、检测请求头过滤

网关权限控制责任链模式

在网关作为微服务程序的入口,拦截客户端所有的请求实现权限控制 ,比如先判断Api接口限流、黑名单、用户会话、参数过滤。
Api接口限流→黑名单拦截→用户会话→参数过滤

责任链的实现

基于工厂模式实现责任链

public abstract class GatewayHandler {

    /**
     * 处理业务逻辑
     */
    public abstract void doService();

    public GatewayHandler(GatewayHandler gatewayHandler) {
        this.gatewayHandler = gatewayHandler;
    }

    private GatewayHandler gatewayHandler;

    protected void nextService() {
        if (gatewayHandler != null) {
            gatewayHandler.doService();
        }
    }

}
@Slf4j
public class CurrentLimitHandler extends GatewayHandler {

    public CurrentLimitHandler(GatewayHandler blacklistHandler) {
        super(blacklistHandler);
    }


    @Override
    public void doService() {
        log.info(">>第一关api接口限流<<");
        nextService();
    }


}
@Slf4j
public class BlacklistHandler extends GatewayHandler {

    public BlacklistHandler(GatewayHandler conversationHandler) {
        super(conversationHandler);
    }

    @Override
    public void doService() {
        log.info(">>第二关黑名单拦截<<");
        nextService();
    }


}
@Slf4j
public class ConversationHandler extends GatewayHandler {
    private GatewayHandler gatewayHandler;

    public ConversationHandler(GatewayHandler gatewayHandler) {
        super(gatewayHandler);
    }

    @Override
    public void doService() {
        log.info(">>>>第三关-判断用户的会话信息 <<<");
    }
}

public class FactoryHandler {

    /**
     * 获取第一个currentLimitHandler
     *
     * @return
     */
    public static GatewayHandler getFirstGatewayHandler() {
        CurrentLimitHandler currentLimitHandler =
                new CurrentLimitHandler(new BlacklistHandler(new ConversationHandler(null)));
        return currentLimitHandler;
    }
}

基于数据库模式实现责任链
数据库表结构
CREATE TABLE gateway_handler (
ID int(11) NOT NULL AUTO_INCREMENT COMMENT ‘主键ID’,
handler_name varchar(32) DEFAULT NULL COMMENT ‘handler名称’,
handler_id varchar(32) DEFAULT NULL COMMENT ‘handler主键id’,
prev_handler_id varchar(32) DEFAULT NULL,
next_handler_id varchar(32) DEFAULT NULL COMMENT ‘下一个handler’,
PRIMARY KEY (ID)
) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8 COMMENT=‘权限表’;


– Records of gateway_handler


INSERT INTO gateway_handler VALUES (‘16’, ‘Api接口限流’, ‘currentLimitHandler’, null, ‘blacklistHandler’);
INSERT INTO gateway_handler VALUES (‘17’, ‘黑名单拦截’, ‘blacklistHandler’, ‘currentLimitHandler’, ‘conversationHandler’);
INSERT INTO gateway_handler VALUES (‘18’, ‘会话验证’, ‘conversationHandler’, ‘blacklistHandler’, null);


@Component
@Slf4j
public class DbHanlder {

    @Autowired
    private GatewayHandlerMapper gatewayHandlerMapper;

    public GatewayHandler getFirstGatewayHandler() {
        //1.查找到链表头部
        QueryWrapper<GatewayHandlerEntity> queryHeadWrapper = new QueryWrapper<GatewayHandlerEntity>();
        queryHeadWrapper.isNull("prev_handler_id");
        GatewayHandlerEntity gatewayHeadHandlerEntity = gatewayHandlerMapper.selectOne(queryHeadWrapper);
        if (gatewayHeadHandlerEntity == null) {
            log.info(">>>数据库中没有配置链表头部<<");
            return null;
        }

        // 2.从Spring中查找到该头对象
        GatewayHandler gatewayHeadHandler = SpringUtils.getBean(gatewayHeadHandlerEntity.getHandlerId(),
                GatewayHandler.class);
        if (gatewayHeadHandler == null) {
            log.info(">>>在相聚中没有配置<<" + gatewayHeadHandler);
            return null;
        }
        //3.关联NextGatewayHandler
        String nextHandlerId = gatewayHeadHandlerEntity.getNextHandlerId();

        // 4.创建临时对象指针
        GatewayHandler tempGatewayHeadHandler = gatewayHeadHandler;
        while (StringUtils.isNoneBlank(nextHandlerId)) {
            GatewayHandler gatewayNextHandler = SpringUtils.getBean(nextHandlerId, GatewayHandler.class);
            if (gatewayNextHandler == null) {
                return null;
            }

            //4.查询下一个节点
            QueryWrapper queryNextWrapper = new QueryWrapper<GatewayHandlerEntity>();
            queryNextWrapper.eq("handler_id", nextHandlerId);
            GatewayHandlerEntity gatewayNextHandlerEntity = gatewayHandlerMapper.selectOne(queryNextWrapper);
            nextHandlerId = gatewayNextHandlerEntity.getNextHandlerId();
            tempGatewayHeadHandler.setGatewayHandler(gatewayNextHandler);
            tempGatewayHeadHandler = gatewayNextHandler;
        }
        return gatewayHeadHandler;
    }
}

基于策略模式实现发送消息

策略模式基本概念
策略模式是对算法的包装,是把使用算法的责任和算法本身分割开来,委派给不同的对象管理,最终可以实现解决多重if判断问题。

1.环境(Context)角色:持有一个Strategy的引用。
2.抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
3.具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。

定义策略接口->实现不同的策略类->利用多态或其他方式调用策略

策略模式应用场景
1.异步实现发送短信 比如阿里云、腾讯云、其他短信渠道等
2.聚合支付系统 银联支付、支付宝、微信支付等
3.联合登陆 QQ、钉钉、微信联合登陆渠道等
策略模式实现的方式
基于工厂模式实现

public interface MsgStrategy {
    String sendMsg();
}

public class AliYunStrategy implements MsgStrategy {
    public String sendMsg() {
        return "阿里云";
    }
}
public class HuaWeiStrategy implements MsgStrategy {
    public String sendMsg() {
        return "华为云";
    }
}
public class TencentStrategy implements MsgStrategy {
    public String sendMsg() {
        return "腾讯云";
    }
}


public class FactoryStrategy {

    /**
     * 存放策略的容器
     */
    private static Map<String, MsgStrategy> strategys = new ConcurrentHashMap<String, MsgStrategy>();

    static {
        strategys.put("aliYunStrategy", new AliYunStrategy());
        strategys.put("tencentStrategy", new TencentStrategy());
        strategys.put("huaWeiStrategy", new HuaWeiStrategy());
    }

    public static MsgStrategy getMsgStrategy(String strategyId) {
        return strategys.get(strategyId);
    }
}

基于数据库模式实现
数据库表结构
DROP TABLE IF EXISTS meite_strategy;
CREATE TABLE meite_strategy (
ID int(11) NOT NULL AUTO_INCREMENT COMMENT ‘ID’,
strategy_NAME varchar(32) NOT NULL COMMENT ‘策略名称’,
strategy_ID varchar(32) NOT NULL COMMENT ‘策略ID’,
strategy_type varchar(32) NOT NULL COMMENT ‘策略ID’,
strategy_bean_id varchar(255) DEFAULT NULL COMMENT ‘策略执行beanid’,
PRIMARY KEY (ID)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8 COMMENT=‘策略’;


– Records of meite_strategy


INSERT INTO `meite_strategy` VALUES ('6', '腾讯云', 'tencent_sms', 'send_msg', 'tencentStrategy');
INSERT INTO `meite_strategy` VALUES ('7', '阿里云', 'aliYun_sms', 'send_msg', 'aliYunStrategy');
INSERT INTO `meite_strategy` VALUES ('8', '华为云', 'huaWei_sms', 'send_msg', 'huaWeiStrategy');
INSERT INTO `meite_strategy` VALUES ('9', '阿里Pay', 'ali_pay', 'pay', 'aliPayStrategy');
INSERT INTO `meite_strategy` VALUES ('10', '银联Pay', 'yinlian_pay', 'pay', 'unionPayStrategy');

根据策略ID查询策略

@Component
public class StrategyManage {
@Autowired
private StrategyMapper strategyMapper;

public <T> T getStrategy(String strategyId, String strategyType, Class<T> t) {
    if (StringUtils.isEmpty(strategyId)) {
        return null;
    }
    if (StringUtils.isEmpty(strategyType)) {
        return null;
    }
    if (t == null) {
        return null;
    }
    QueryWrapper tQueryWrapper = new QueryWrapper<>();
    tQueryWrapper.eq("strategy_id", strategyId);
    MeiteStrategy meiteStrategy = strategyMapper.selectOne(tQueryWrapper);
    String strategyBeanId = meiteStrategy.getStrategyBeanId();
    if (StringUtils.isEmpty(strategyBeanId)) {
        return null;
    }
    return SpringUtils.getBean(strategyBeanId, t);
}

}