湘西建网站,wordpress 编辑 所见即所得插件,如果给公司网站做网络广告,酷站素材有时候我们会碰到这样的情况#xff1a;有n个场景#xff0c;每个场景都有自己的逻辑#xff0c;即n个处理逻辑#xff0c;这时候我们就需要通过某个参数的值代表这n个场景#xff0c;然后去加载每个场景不同的bean对象#xff0c;即不同的类#xff0c;这些类中都有一个…有时候我们会碰到这样的情况有n个场景每个场景都有自己的逻辑即n个处理逻辑这时候我们就需要通过某个参数的值代表这n个场景然后去加载每个场景不同的bean对象即不同的类这些类中都有一个同名的方法但是里面的逻辑不同类似策略模式、工厂模式等假设这样的场景银行卡分几种类型比如普通会员黄金会员黑卡会员......普通会员、黄金会员和黑卡的权限不一样消费能力不一样等等内容这里我们就以消费的能力举例普通会员只能转账5万元黄金只能转账20万元黑卡100万元我们有3各类分别是Putong.classHuangjin.classHeika.class这三个类里面有一个同样的方法名字叫checkPermissions()方法三个类上都加了一个自定义注解MemberTypeDefinitiondemo自定义注解package com.zygxsq.test;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** 自定义注解***/
Retention(RetentionPolicy.RUNTIME)
Target(ElementType.TYPE)
public interface MemberTypeDefinition {/*** 数据源默认执行方法*/public static final String DEFAULT_DAO_METHOD_NAME checkPermissions;/*** 数据源执行的方法名称, 默认为getData, 该方法必须只有一个参数{link BaseDataSpec}, 返回结果必须是{link BaseResult}, 可见性必须是public** return 方法名称*/String value() default DEFAULT_DAO_METHOD_NAME;
}
Putong.classpackage com.zygxsq.test;import org.springframework.stereotype.Component;/*** 普通会员处理逻辑***/
MemberTypeDefinition
Slf4j
Component
public class Putong {public BaseResult checkPermissions(BaseDataSpec baseDataSpec) {// 省略中间的一些处理逻辑// ......// 省略中间的一些处理逻辑// 最后封装返回结果BaseResult baseResult new BaseResult();baseResult.setResponse(我是普通会员);return baseResult;}
}
Huangjin.classpackage com.zygxsq.test;import org.springframework.stereotype.Component;/*** 黄金会员处理逻辑***/
MemberTypeDefinition
Slf4j
Component
public class Huangjin {public BaseResult checkPermissions(BaseDataSpec baseDataSpec) {// 省略中间的一些处理逻辑// ......// 省略中间的一些处理逻辑// 最后封装返回结果BaseResult baseResult new BaseResult();baseResult.setResponse(我是黄金会员);return baseResult;}
}
Heika.classpackage com.zygxsq.test;import org.springframework.stereotype.Component;/*** 黑卡会员处理逻辑***/
MemberTypeDefinition
Slf4j
Component
public class Heika {public BaseResult checkPermissions(BaseDataSpec baseDataSpec) {// 省略中间的一些处理逻辑// ......// 省略中间的一些处理逻辑// 最后封装返回结果BaseResult baseResult new BaseResult();baseResult.setResponse(我是黑卡会员);return baseResult;}
}
入参和返回参数对象入参对象package com.zygxsq.test;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;import java.io.Serializable;
import java.util.List;/*** 入参数据对象***/
Data
SuperBuilder
NoArgsConstructor
AllArgsConstructor
public class BaseDataSpec implements Serializable {/*** serialVersionUID*/private static final long serialVersionUID -5669150877852962345L;/*** id*/private String id;/*** 名字*/private String name;
}
返回结果对象package com.zygxsq.test;import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;/*** 返回结果对象***/
Data
Builder
NoArgsConstructor
AllArgsConstructor
public class BaseResult implements Serializable {/*** serialVersionUID*/private static final long serialVersionUID 7510262928468530569L;private String response;
}
那如何通过反射进行加载呢BaseDataAnnotationApplication.classpackage com.zygxsq.test;import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;/*** 启动加载***/
Slf4j
Component
public class BaseDataAnnotationApplication implements ApplicationContextAware, InitializingBean {private ApplicationContext applicationContext;/*** className,V*/private final MapString, Object loadMap Maps.newConcurrentMap();/*** 特殊人群表缓存 id,1 ,获取 SpecialPeople.class里面所有的表名*/public static MapString,Object dmTablesMap Maps.newConcurrentMap();Overridepublic void afterPropertiesSet() throws Exception {// 获取加了 MemberTypeDefinition 注解的源表beanloadSourceDefinition();// 获取SpecialPeople.class里面所有的表名loadSpecialMap();}private void loadSourceDefinition() throws Exception{MapString, Object beans applicationContext.getBeansWithAnnotation(MemberTypeDefinition.class);for (final Object serviceObject : beans.values()) {final Class? extends Object calcuteClass serviceObject.getClass();MemberTypeDefinition annotation calcuteClass.getAnnotation(MemberTypeDefinition.class);if (null annotation) {log.error(类 {} 注解缺失, calcuteClass);continue;}loadMap.put(calcuteClass.getName(), serviceObject);}}/*** 获取SpecialPeople.class里面所有的表名* throws Exception*/private void loadSpecialMap() throws Exception {dmTablesMap Maps.newConcurrentMap();Field[] declaredFields SpecialPeople.class.getDeclaredFields();for (Field declaredField : declaredFields) {Class? type declaredField.getType();String typeName declaredField.getGenericType().getTypeName();Class? aClass Class.forName(typeName);if (type People.class) {People people (People) declaredField.get(aClass);String id people.getId().trim();dmTablesMap.put(id, 1);}}}Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext applicationContext;}public T BaseResult buildData(ClassT clazz, BaseDataSpec baseDataSpec) throws Exception{// 获取执行方法名, 默认为getDataString methodName;MemberTypeDefinition annotation clazz.getAnnotation(MemberTypeDefinition.class);if (annotation null || StringUtils.isBlank(annotation.value())) {methodName MemberTypeDefinition.DEFAULT_DAO_METHOD_NAME;} else {methodName annotation.value();}Method method;Object bean loadMap.get(clazz.getName());BaseResult result null;try {method bean.getClass().getMethod(methodName, BaseDataSpec.class);result (BaseResult) method.invoke(bean, baseDataSpec);} catch (NoSuchMethodException e) {throw new Exception(clazz.getName()未找到执行方法methodName);} catch (Exception e2) {throw new Exception(clazz.getName()未找到执行方法methodName);}return result;}public T BaseResult buildData(Class? sourceClass) {return null;}
}
通过上面的application就可以加对象加载到缓存里了如何我们直接调用即可