太倉建設(shè)銀行網(wǎng)站搜索指數(shù)查詢
有時(shí)候我們會碰到這樣的情況:
有n個(gè)場景,每個(gè)場景都有自己的邏輯,即n個(gè)處理邏輯,
這時(shí)候我們就需要通過某個(gè)參數(shù)的值代表這n個(gè)場景,然后去加載每個(gè)場景不同的bean對象,即不同的類,這些類中都有一個(gè)同名的方法,但是里面的邏輯不同,類似策略模式、工廠模式等
假設(shè)這樣的場景,銀行卡分幾種類型,比如普通會員,黃金會員,黑卡會員......
普通會員、黃金會員和黑卡的權(quán)限不一樣,消費(fèi)能力不一樣等等內(nèi)容,這里我們就以消費(fèi)的能力舉例,普通會員只能轉(zhuǎn)賬5萬元,黃金只能轉(zhuǎn)賬20萬元,黑卡100萬元,
我們有3各類,分別是Putong.class,Huangjin.class,Heika.class,這三個(gè)類里面有一個(gè)同樣的方法,名字叫:checkPermissions()方法,三個(gè)類上都加了一個(gè)自定義注解@MemberTypeDefinition
demo
自定義注解
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 {/*** 數(shù)據(jù)源默認(rèn)執(zhí)行方法*/public static final String DEFAULT_DAO_METHOD_NAME = "checkPermissions";/*** 數(shù)據(jù)源執(zhí)行的方法名稱, 默認(rèn)為getData, 該方法必須只有一個(gè)參數(shù){@link BaseDataSpec}, 返回結(jié)果必須是{@link BaseResult}, 可見性必須是public** @return 方法名稱*/String value() default DEFAULT_DAO_METHOD_NAME;
}
Putong.class
package com.zygxsq.test;import org.springframework.stereotype.Component;/*** 普通會員處理邏輯***/
@MemberTypeDefinition
@Slf4j
@Component
public class Putong {public BaseResult checkPermissions(BaseDataSpec baseDataSpec) {// 省略中間的一些處理邏輯// ......// 省略中間的一些處理邏輯// 最后封裝返回結(jié)果BaseResult baseResult = new BaseResult();baseResult.setResponse("我是普通會員");return baseResult;}
}
Huangjin.class
package com.zygxsq.test;import org.springframework.stereotype.Component;/*** 黃金會員處理邏輯***/
@MemberTypeDefinition
@Slf4j
@Component
public class Huangjin {public BaseResult checkPermissions(BaseDataSpec baseDataSpec) {// 省略中間的一些處理邏輯// ......// 省略中間的一些處理邏輯// 最后封裝返回結(jié)果BaseResult baseResult = new BaseResult();baseResult.setResponse("我是黃金會員");return baseResult;}
}
Heika.class
package com.zygxsq.test;import org.springframework.stereotype.Component;/*** 黑卡會員處理邏輯***/
@MemberTypeDefinition
@Slf4j
@Component
public class Heika {public BaseResult checkPermissions(BaseDataSpec baseDataSpec) {// 省略中間的一些處理邏輯// ......// 省略中間的一些處理邏輯// 最后封裝返回結(jié)果BaseResult baseResult = new BaseResult();baseResult.setResponse("我是黑卡會員");return baseResult;}
}
入?yún)⒑头祷貐?shù)對象
入?yún)ο?/p>
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;/*** 入?yún)?shù)據(jù)對象***/
@Data
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class BaseDataSpec implements Serializable {/*** serialVersionUID*/private static final long serialVersionUID = -5669150877852962345L;/*** id*/private String id;/*** 名字*/private String name;
}
返回結(jié)果對象
package com.zygxsq.test;import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;/*** 返回結(jié)果對象***/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class BaseResult implements Serializable {/*** serialVersionUID*/private static final long serialVersionUID = 7510262928468530569L;private String response;
}
那如何通過反射進(jìn)行加載呢,BaseDataAnnotationApplication.class
package 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 Map<String, Object> loadMap = Maps.newConcurrentMap();/*** 特殊人群表緩存 <id,1> ,獲取 SpecialPeople.class里面所有的表名*/public static Map<String,Object> dmTablesMap = Maps.newConcurrentMap();@Overridepublic void afterPropertiesSet() throws Exception {// 獲取加了 MemberTypeDefinition 注解的源表beanloadSourceDefinition();// 獲取SpecialPeople.class里面所有的表名loadSpecialMap();}private void loadSourceDefinition() throws Exception{Map<String, 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(Class<T> clazz, BaseDataSpec baseDataSpec) throws Exception{// 獲取執(zhí)行方法名, 默認(rèn)為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()+"未找到執(zhí)行方法:"+methodName);} catch (Exception e2) {throw new Exception(clazz.getName()+"未找到執(zhí)行方法:"+methodName);}return result;}public <T> BaseResult buildData(Class<?> sourceClass) {return null;}
}
通過上面的application,就可以加對象加載到緩存里了,如何我們直接調(diào)用即可