首先在spring容器启动时加载所有规则校验类。
在SpringObjectCheckManagerFactory类的afterPropertiesSet()方法中进行加载。所有规则校验类都实现自ObjectCheck接口。
package com.taobao.member.prop.ao.check;
import com.alibaba.common.logging.Logger;
import com.alibaba.common.logging.LoggerFactory;
import com.taobao.member.prop.ao.check.concreteObjectCheck.CheckForReceiveTime;
import com.taobao.member.prop.ao.check.concreteObjectCheck.CheckForUseTime;
import com.taobao.member.prop.ao.check.impl.ObjectCheckManagerImpl;
import com.taobao.member.prop.timetask.PropTimerTask;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
*
* @author zirou
*
*/
@Component("objectCheckManager")
public class SpringObjectCheckManagerFactory implements InitializingBean, FactoryBean, ApplicationContextAware {
private Logger logger = LoggerFactory.getLogger(SpringObjectCheckManagerFactory.class);
private ApplicationContext context;
public void setApplicationContext(ApplicationContext applicationContext)throws BeansException {
this.context = applicationContext;
}
@Autowired
private ObjectCheckManagerImpl objectCheckManager;
@Autowired
private PropTimerTask propTimerTask;
public Object getObject() throws Exception {
return objectCheckManager;
}
public Class<ObjectCheckManager> getObjectType() {
return ObjectCheckManager.class;
}
public boolean isSingleton() {
return true;
}
public void afterPropertiesSet() throws Exception {
propTimerTask.start();
Map<String, ObjectCheck> objectCheckListMap = objectCheckManager.getObjectCheckListMap();
String[] objectCheckNames = context.getBeanNamesForType(ObjectCheck.class, true, false);//String[] getBeanNamesForType(Class type, boolean includePrototypes, boolean includeFactoryBeans);
if ((objectCheckNames != null) && (objectCheckNames.length > 0)) {
for (String objectCheckName : objectCheckNames) {
ObjectCheck objectCheck = (ObjectCheck) context.getBean(objectCheckName, ObjectCheck.class);
ObjectCheck objectCheckInMap = objectCheckListMap.get(objectCheck.getCheckName());
if (objectCheckInMap == null) {
objectCheckListMap.put(objectCheck.getCheckName(), objectCheck);
}
}
} else {
logger.warn("No ObjectCheck is defined in the spring container");
}
objectCheckManager.setObjectCheckListMap(objectCheckListMap);
//领取时间
ObjectCheck checkForReceiveTime= objectCheckListMap.get("com.taobao.member.prop.ao.check.concreteObjectCheck.CheckForReceiveTime");
Map<String, ConditionValue> receiveMap = ((CheckForReceiveTime) checkForReceiveTime).getConditionValueMap();
String[] conditionValueNames = context.getBeanNamesForType(ConditionValue.class, true, false);
if ((conditionValueNames != null) && (conditionValueNames.length > 0)) {
for (String conditionValueName : conditionValueNames) {
ConditionValue conditionValue = (ConditionValue) context.getBean(conditionValueName, ConditionValue.class);
ConditionValue conditionValueInMap = receiveMap.get(conditionValue.getConditionValueName());
if (conditionValueInMap == null) {
receiveMap.put(conditionValue.getConditionValueName(), conditionValue);
}
}
} else {
logger.warn("No ObjectCheck is defined in the spring container");
}
((CheckForReceiveTime) checkForReceiveTime).setConditionValueMap(receiveMap);
//使用时间
ObjectCheck checkForUseTime= objectCheckListMap.get("com.taobao.member.prop.ao.check.concreteObjectCheck.CheckForUseTime");
Map<String, ConditionValue> useMap = ((CheckForUseTime) checkForUseTime).getConditionValueMap();
if ((conditionValueNames != null) && (conditionValueNames.length > 0)) {
for (String conditionValueName : conditionValueNames) {
ConditionValue conditionValue = (ConditionValue) context.getBean(conditionValueName, ConditionValue.class);
ConditionValue conditionValueInMap = useMap.get(conditionValue.getConditionValueName());
if (conditionValueInMap == null) {
useMap.put(conditionValue.getConditionValueName(), conditionValue);
}
}
} else {
logger.warn("No ObjectCheck is defined in the spring container");
}
((CheckForUseTime) checkForUseTime).setConditionValueMap(useMap);
}
}
SpringObjectCheckManagerFactory类的afterPropertiesSet()方法首先通过String[] objectCheckNames = context.getBeanNamesForType(ObjectCheck.class, true, false);从applicationContext中取所有继承了ObjectCheck的校验类的名称,通过ObjectCheck objectCheck = (ObjectCheck) context.getBean(objectCheckName, ObjectCheck.class);取名称对应的类实例。然后将类名称和实例分别作为key和value,put到ObjectCheckManagerImpl的objectCheckListMap中。
下面是ObjectCheck的一个实现类,特意选这个对使用时间进行校验的例子,是为了跟SpringObjectCheckManagerFactory中“使用时间”部分联系起来看,看看是如何仅在数据库中配置了类名却通过这个类的实例来进行使用时间的校验的。从上面已经put好的objectCheckListMap中取“使用时间”的类实例,再取它的conditionValueMap,将所有实现了ConditionValue接口的类都put进conditionValueMap,set回去。通过这样的方式,我们开发一个类,在数据库中一条记录里配置上全类名,就可以用其实例来进行校验了。
import com.taobao.member.domain.prop.TmallPropRuleConfineDO;
import com.taobao.member.prop.ao.check.ConditionValue;
import com.taobao.member.prop.ao.check.ObjectCheck;
import com.taobao.member.prop.ao.check.ObjectCheckCodeConstant;
import com.taobao.member.prop.ao.check.QueryRuleConfine;
import com.taobao.member.prop.ao.ruleConfine.Branch;
import com.taobao.member.prop.ao.ruleConfine.Node;
import com.taobao.member.prop.ao.ruleConfine.RuleOperate;
import com.taobao.member.service.prop.PropConstants;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
*
* @author zirou
*
*/
@Component
public class CheckForUseTime implements ObjectCheck<QueryRuleConfine>{
Map<String,ConditionValue> conditionValueMap= new HashMap<String,ConditionValue>();
public Map<String, ConditionValue> getConditionValueMap() {
return conditionValueMap;
}
public void setConditionValueMap(Map<String, ConditionValue> conditionValueMap) {
this.conditionValueMap = conditionValueMap;
}
@Override
public String check(QueryRuleConfine queryRuleConfine) {
String result = ObjectCheckCodeConstant.OBJECT_CHECK_TRUE_CODE+":"+this.getCheckName();
TmallPropRuleConfineDO memberPropRuleConfineDO = this.buildMemberCorrespondRule(queryRuleConfine);
List<TmallPropRuleConfineDO> memberRuleTypeList = new ArrayList<TmallPropRuleConfineDO>();
List<TmallPropRuleConfineDO> thisRuleTypeList = new ArrayList<TmallPropRuleConfineDO>();
for(TmallPropRuleConfineDO tmallPropRuleConfineDO:queryRuleConfine.getUsePropRuleConfineList()){
if(tmallPropRuleConfineDO.getRuleType()==PropConstants.PROP_RULE_CONFINE_RULE_TYPE_USE_TIME){
if(tmallPropRuleConfineDO.getMemberLevel()==Integer.MIN_VALUE){//同一个propItemId的同一个rule_type下面,不可能同时存在有会员等级的和无等级的
tmallPropRuleConfineDO.setMemberLevel(queryRuleConfine.getMemberLevel());
}
thisRuleTypeList.add(tmallPropRuleConfineDO);
}
}
if(thisRuleTypeList.size()>0){
Branch root = RuleOperate.createRuleTree(thisRuleTypeList);
Node matchNode = RuleOperate.findContainsNode(root,memberPropRuleConfineDO);
if(matchNode.getPosition()==2){
ArrayList<Node> leafNodes = ((Branch)matchNode).getChildren();
Map existPart = (Map) leafNodes.get(0).getValue();
if(existPart.containsKey(PropConstants.PROP_RULE_CONFINE_CONDITION_KEY_TIME)){
if(memberPropRuleConfineDO.getConditionValue()!=null && !"".equals(memberPropRuleConfineDO.getConditionValue())){
ConditionValue conditionValue = conditionValueMap.get(memberPropRuleConfineDO.getConditionValue());
boolean isSatisfy = conditionValue.isSatisfyTimeConfine(queryRuleConfine);
if(isSatisfy){
memberPropRuleConfineDO.setConditionKey(PropConstants.PROP_RULE_CONFINE_CONDITION_KEY_TIME);
memberPropRuleConfineDO.setConditionValue(memberPropRuleConfineDO.getConditionValue());
memberRuleTypeList.add(memberPropRuleConfineDO);
}else{
return "不满足使用的时间条件限制:"+this.getCheckName();
}
}
}
}else{
return ObjectCheckCodeConstant.OBJECT_CHECK_FALSE_CODE+":"+this.getCheckName();
}
Branch rootDeleted = RuleOperate.deleteTree(root, memberRuleTypeList);
boolean boo = RuleOperate.isAllEmptyLeaves(rootDeleted);
if(!boo) {
return ObjectCheckCodeConstant.OBJECT_CHECK_FALSE_CODE+":"+this.getCheckName();
}
}
return result;
}
protected TmallPropRuleConfineDO buildMemberCorrespondRule(QueryRuleConfine queryRuleConfine) {
TmallPropRuleConfineDO tmallPropRuleConfineDO = new TmallPropRuleConfineDO();
tmallPropRuleConfineDO.setPropId(queryRuleConfine.getPropId());
tmallPropRuleConfineDO.setPropItemId(queryRuleConfine.getPropItemId());
tmallPropRuleConfineDO.setMemberLevel(queryRuleConfine.getMemberLevel());
tmallPropRuleConfineDO.setRuleType(PropConstants.PROP_RULE_CONFINE_RULE_TYPE_USE_TIME);
tmallPropRuleConfineDO.setConditionValue(queryRuleConfine.getUseTimeProcessorClassName());
return tmallPropRuleConfineDO;
}
@Override
public int getBizType() {
return PropConstants.PROP_RULE_CONFINE_RULE_TYPE_USE_TIME;
}
@Override
public String getCheckName() {
return CheckForUseTime.class.getName();
}
}
到此时,我们已经将所有校验的规则加载起来了,在使用时通过调用propManager的isSatisfyRuleConfine(queryRuleConfine, PropConstants.BIZ_TYPE_RECEIVE);方法进行校验。propManager调用objectCheckService的check(queryRuleConfine, bizType);方法。
import com.alibaba.common.logging.Logger;
import com.alibaba.common.logging.LoggerFactory;
import com.taobao.member.exception.MemberException;
import com.taobao.member.prop.ao.check.ObjectCheck;
import com.taobao.member.prop.ao.check.ObjectCheckCodeConstant;
import com.taobao.member.prop.ao.check.ObjectCheckManager;
import com.taobao.member.prop.ao.check.ObjectCheckService;
import com.taobao.member.service.prop.PropConstants;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
*
* @author zirou
*
*/
@Component("objectCheckServiceImpl")
public class ObjectCheckServiceImpl implements ObjectCheckService,InitializingBean {
private Logger logger = LoggerFactory.getLogger(ObjectCheckServiceImpl.class);
private ObjectCheckManager objectCheckManager;
public void setObjectCheckManager(ObjectCheckManager objectCheckManager) {
this.objectCheckManager = objectCheckManager;
}
private ExecutorService executorService;
public void afterPropertiesSet() throws Exception {
init();
}
public void init() {
executorService = Executors.newCachedThreadPool();
}
@Override
public List<String> check(Object obj, int bizType) {
List<String> featureResult = Collections.synchronizedList(new ArrayList<String>());
List<ObjectCheck> objCheckList = objectCheckManager.getObjectCheckListByObject(obj);
// 组装需要工作的对象检查器
List<ObjectCheck> objCheckWorkList = new ArrayList<ObjectCheck>();
if (objCheckList != null && objCheckList.size()>0) {
if(PropConstants.ALL_BIZ_TYPE == bizType){
objCheckWorkList = objCheckList;
}else if(PropConstants.BIZ_TYPE_RECEIVE == bizType){
for (ObjectCheck objectCheck : objCheckList) {
if (PropConstants.ALL_BIZ_TYPE<=objectCheck.getBizType() && objectCheck.getBizType()<=PropConstants.BIZ_TYPE_RECEIVE) {
objCheckWorkList.add(objectCheck);
}
}
}else if(PropConstants.BIZ_TYPE_USE == bizType){
for (ObjectCheck objectCheck : objCheckList) {
if (PropConstants.ALL_BIZ_TYPE>=objectCheck.getBizType() && objectCheck.getBizType()>=PropConstants.BIZ_TYPE_USE) {
objCheckWorkList.add(objectCheck);
}
}
}else{
for (ObjectCheck objectCheck : objCheckList) {
if (bizType == objectCheck.getBizType()
|| PropConstants.ALL_BIZ_TYPE == bizType
|| PropConstants.ALL_BIZ_TYPE == objectCheck.getBizType()) {
objCheckWorkList.add(objectCheck);
}
}
}
}
if (objCheckWorkList.size() > 0) {
CountDownLatch doneSignal = new CountDownLatch(objCheckWorkList.size());
for (ObjectCheck objCheck : objCheckWorkList){
executorService.execute(new WorkerRunnable(doneSignal, objCheck, featureResult, obj));// create and start threads
}
try {
doneSignal.await();
} catch (InterruptedException e) {
logger.error("object_check_time_out_error,the obj className is {"+ obj.getClass().getName() + "}");
featureResult.add(ObjectCheckCodeConstant.OBJECT_CHECK_TIME_OUT_ERROR_CODE);
throw new MemberException(e);
}
}
return featureResult;
}
class WorkerRunnable implements Runnable {
private final CountDownLatch doneSignal;
private final ObjectCheck objectCheck;
private final List<String> featureResult;
private final Object obj;
WorkerRunnable(CountDownLatch doneSignal, ObjectCheck objectCheck,List<String> featureResult, Object obj) {
this.doneSignal = doneSignal;
this.objectCheck = objectCheck;
this.featureResult = featureResult;
this.obj = obj;
}
public void run() {
String result = doWork(objectCheck);
featureResult.add(result);
doneSignal.countDown();
}
String doWork(ObjectCheck objectCheck) {
String result = ObjectCheckCodeConstant.NONE_DEFINED_OBJECT_CHECK_ERROR_CODE;
try {
result = objectCheck.check(obj);
} catch (Exception e) {
logger.error("objCheck throw Exception ,the obj's className is {"
+ obj.getClass().getName() + "} and "
+ "the objectCheck class is {"
+ objectCheck.getClass().getName() + "}", e);
}
return result;
}
}
}
check方法首先取已经初始化好的objectCheckManagerImpl的objectCheckListMap,根据是领取还是使用,从这个objectCheckListMap过滤出校验的规则限制列表,对其中的每条规则校验通过从线程池中取到的某线程进行校验。