动态代理实现规则降级
public class DegraderableRuleWrapper implements FactoryBean, BeanNameAware {private final static Logger LOG = LoggerFactory.getLogger(DegraderableRuleWrapper.class);private final static String ITEM_RULE_NAME_SKIP_NAME = "com.***.ruleSkipNameList";/** * 需要跳过的规则列表 */private static Set<String> skipRuleNameList = Sets.newHashSet();/** * 用于分隔字符串的工具类 */private static final Splitter SPLITTER = Splitter.on(',').omitEmptyStrings().trimResults();private Rule target;private String ruleName; private Object delegate;public void setTarget(Rule target) {this.target = target;//ruleName = target.getClass().getSimpleName();}@Overridepublic void setBeanName(String name) {ruleName = name;}@Overridepublic Object getObject() throws Exception {if (delegate == null) {delegate = createProxy();}return delegate;}private Object createProxy() {@SuppressWarnings("unchecked")Class<?>[] allInterfaces = (Class<?>[]) ClassUtils.getAllInterfaces(target.getClass()).toArray(new Class<?>[0]);Object wrapperedRule = Proxy.newProxyInstance(target.getClass().getClassLoader(), allInterfaces, new SwitchListener());LOG.warn("create a degraderableRule for rule {}.", ruleName);return wrapperedRule;}@Overridepublic Class<? extends Rule> getObjectType() {return Rule.class;}@Overridepublic boolean isSingleton() {return false;}static{initialSkipRuleListAndListenChange();}private static void initialSkipRuleListAndListenChange() {/* * 开始并不主动拉取,而是注册监听,等待异步回调,减少应用启动时间。 */Diamond.addListener(ITEM_RULE_NAME_SKIP_NAME, Constants.DEFAULT_GROUP, new ManagerListenerAdapter() {@Overridepublic void receiveConfigInfo(String configInfo) {LOG.warn("Got new skipRuleNameList, " + configInfo);Iterable<String> ruleNames = SPLITTER.split(configInfo);Set<String> newSkipRuleNames = Sets.newHashSet(ruleNames);skipRuleNameList = newSkipRuleNames;}});}private class SwitchListener implements InvocationHandler {@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {if (skipRuleNameList.contains(ruleName)) {LOG.warn("Rule {} is in skipList, skip it.", ruleName);return RuleResult.successResult();}return method.invoke(target, args);}}}
?实现中使用了spring的factorybean,beanname,google的guava工具类以及淘宝开源的diamond集中式静态配置管理工具。PS:diamond主要是实现对集群的配置管理,其他的方式也很多,比如使用zookeeper也可以,当然使用存储+线程定时轮询变化(其实diamond的实现方式就很类似,只不过加上了比较多的容灾功能)也OK。
对于实现需要注意的是这行代码:
Class<?>[] allInterfaces = (Class<?>[]) ClassUtils.getAllInterfaces(target.getClass()).toArray(new Class<?>[0]);
?开始的时候直接使用
target.getClass().getInterfaces()
?发现继承过来的实现,获取不到类实现的接口,也算是细节的一个点吧。
?
使用这个规则的地方只需要配置下这个bean即可,配置方式如下:
<bean id="testPlatformRule" /></property></bean>
?这样其他地方在引用这个bean的时候就已经是进行了降级管理的Rule了,这样实现了降级功能的统一管理和规则本身的职责单一性。