网页设计模板免费网站,网络营销方式有哪些类型,中国交通建设集团,微网站内容目录
1.扩展点使用实例
2.主要技术点
2.1 注解加持
2.2 注解解析
2.3 扩展点路由 在实际项目中#xff0c;我们经常使用策略模式、或者状态模式来隔离同一接口下不同的实现逻辑#xff0c;进而消除代码中ifelse硬编码分支#xff0c;使代码结构更清晰#xff0c;也大大…目录
1.扩展点使用实例
2.主要技术点
2.1 注解加持
2.2 注解解析
2.3 扩展点路由 在实际项目中我们经常使用策略模式、或者状态模式来隔离同一接口下不同的实现逻辑进而消除代码中ifelse硬编码分支使代码结构更清晰也大大提升了代码可读性同时也满足了“开闭原则”具备更高的可扩展性
在cola架构中给出了一种“扩展点”的思路本质还是策略模式的实现方式通过“扩展点注解”的组装方式将策略模式实现类注册到容器中供后续场景逻辑决策使用
1.扩展点使用实例
首先通过实例了解下cola 扩展点的使用方式
1.首先定义一个SomeExtPt接口并实现ExtensionPointI接口
public interface SomeExtPt extends ExtensionPointI {public void doSomeThing();
}
2.具体实现SomeExtPt接口这里给出了2个实现类如下
Extension(bizId A)
Component
public class SomeExtensionA implements SomeExtPt {Overridepublic void doSomeThing() {System.out.println(SomeExtensionA::doSomething);}}
Extension(bizId B)
Component
public class SomeExtensionB implements SomeExtPt {Overridepublic void doSomeThing() {System.out.println(SomeExtensionB::doSomething);}}
3.测试方法
RunWith(SpringJUnit4ClassRunner.class)
SpringBootTest(classes Application.class)
public class ExtensionRegisterTest {Resourceprivate ExtensionRegister register;Resourceprivate ExtensionExecutor executor;Testpublic void test() {SomeExtPt extA new SomeExtensionA();register.doRegistration(extA);SomeExtPt extB CglibProxyFactory.createProxy(new SomeExtensionB());register.doRegistration(extB);executor.executeVoid(SomeExtPt.class, BizScenario.valueOf(A), SomeExtPt::doSomeThing);executor.executeVoid(SomeExtPt.class, BizScenario.valueOf(B), SomeExtPt::doSomeThing);}}
public class CglibProxyFactory {public static T T createProxy(T object) {Enhancer enhancer new Enhancer();enhancer.setSuperclass(object.getClass());enhancer.setCallback(new ProxyCallback(object));return (T) enhancer.create();}public static class ProxyCallback implements MethodInterceptor {private Object target;public ProxyCallback(Object target) {this.target target;}Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println(ProxyObject::before);Object object proxy.invoke(target, args);System.out.println(ProxyObject::after);return object;}}
}
2.主要技术点
2.1 注解加持
上述具体策略接口实现方法标注了扩展点注解Extension
Inherited
Retention(RetentionPolicy.RUNTIME)
Target({ElementType.TYPE})
Repeatable(Extensions.class)
Component
public interface Extension {String bizId() default BizScenario.DEFAULT_BIZ_ID;String useCase() default BizScenario.DEFAULT_USE_CASE;String scenario() default BizScenario.DEFAULT_SCENARIO;
}
所有的具体实现方法都需要标注该注解表明该类属于一个扩展点同时由于标注了Component注解表明每一个扩展点也是一个bean实例
2.2 注解解析
扩展点注解的解析工作主要借助类ExtensionBootstrap和ExtensionRegister完成
Component
public class ExtensionBootstrap implements ApplicationContextAware {Resourceprivate ExtensionRegister extensionRegister;private ApplicationContext applicationContext;PostConstructpublic void init(){MapString, Object extensionBeans applicationContext.getBeansWithAnnotation(Extension.class);extensionBeans.values().forEach(extension - extensionRegister.doRegistration((ExtensionPointI) extension));// handle Extensions annotationMapString, Object extensionsBeans applicationContext.getBeansWithAnnotation(Extensions.class);extensionsBeans.values().forEach( extension - extensionRegister.doRegistrationExtensions((ExtensionPointI) extension));}Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext applicationContext;}
}
Component
public class ExtensionRegister {/*** 扩展点接口名称不合法*/private static final String EXTENSION_INTERFACE_NAME_ILLEGAL extension_interface_name_illegal;/*** 扩展点不合法*/private static final String EXTENSION_ILLEGAL extension_illegal;/*** 扩展点定义重复*/private static final String EXTENSION_DEFINE_DUPLICATE extension_define_duplicate;Resourceprivate ExtensionRepository extensionRepository;public final static String EXTENSION_EXTPT_NAMING ExtPt;public void doRegistration(ExtensionPointI extensionObject) {Class? extensionClz extensionObject.getClass();if (AopUtils.isAopProxy(extensionObject)) {extensionClz ClassUtils.getUserClass(extensionObject);}Extension extensionAnn AnnotationUtils.findAnnotation(extensionClz, Extension.class);BizScenario bizScenario BizScenario.valueOf(extensionAnn.bizId(), extensionAnn.useCase(), extensionAnn.scenario());ExtensionCoordinate extensionCoordinate new ExtensionCoordinate(calculateExtensionPoint(extensionClz), bizScenario.getUniqueIdentity());ExtensionPointI preVal extensionRepository.getExtensionRepo().put(extensionCoordinate, extensionObject);if (preVal ! null) {String errMessage Duplicate registration is not allowed for : extensionCoordinate;throw new ExtensionException(EXTENSION_DEFINE_DUPLICATE, errMessage);}}public void doRegistrationExtensions(ExtensionPointI extensionObject){Class? extensionClz extensionObject.getClass();if (AopUtils.isAopProxy(extensionObject)) {extensionClz ClassUtils.getUserClass(extensionObject);}Extensions extensionsAnnotation AnnotationUtils.findAnnotation(extensionClz, Extensions.class);Extension[] extensions extensionsAnnotation.value();if (!ObjectUtils.isEmpty(extensions)){for (Extension extensionAnn : extensions) {BizScenario bizScenario BizScenario.valueOf(extensionAnn.bizId(), extensionAnn.useCase(), extensionAnn.scenario());ExtensionCoordinate extensionCoordinate new ExtensionCoordinate(calculateExtensionPoint(extensionClz), bizScenario.getUniqueIdentity());ExtensionPointI preVal extensionRepository.getExtensionRepo().put(extensionCoordinate, extensionObject);if (preVal ! null) {String errMessage Duplicate registration is not allowed for : extensionCoordinate;throw new ExtensionException(EXTENSION_DEFINE_DUPLICATE, errMessage);}}}//String[] bizIds extensionsAnnotation.bizId();String[] useCases extensionsAnnotation.useCase();String[] scenarios extensionsAnnotation.scenario();for (String bizId : bizIds) {for (String useCase : useCases) {for (String scenario : scenarios) {BizScenario bizScenario BizScenario.valueOf(bizId, useCase, scenario);ExtensionCoordinate extensionCoordinate new ExtensionCoordinate(calculateExtensionPoint(extensionClz), bizScenario.getUniqueIdentity());ExtensionPointI preVal extensionRepository.getExtensionRepo().put(extensionCoordinate, extensionObject);if (preVal ! null) {String errMessage Duplicate registration is not allowed for : extensionCoordinate;throw new ExtensionException(EXTENSION_DEFINE_DUPLICATE, errMessage);}}}}}/*** param targetClz* return*/private String calculateExtensionPoint(Class? targetClz) {Class?[] interfaces ClassUtils.getAllInterfacesForClass(targetClz);if (interfaces null || interfaces.length 0) {throw new ExtensionException(EXTENSION_ILLEGAL, Please assign a extension point interface for targetClz);}for (Class intf : interfaces) {String extensionPoint intf.getSimpleName();if (extensionPoint.contains(EXTENSION_EXTPT_NAMING)) {return intf.getName();}}String errMessage Your name of ExtensionPoint for targetClz is not valid, must be end of EXTENSION_EXTPT_NAMING;throw new ExtensionException(EXTENSION_INTERFACE_NAME_ILLEGAL, errMessage);}}
最终将扩展点和决策条件的映射关系存储到ExtensionRepository中
Component
public class ExtensionRepository {public MapExtensionCoordinate, ExtensionPointI getExtensionRepo() {return extensionRepo;}private MapExtensionCoordinate, ExtensionPointI extensionRepo new HashMap();}
2.3 扩展点路由
在实际业务场景调度过程中会调用ExtensionExecutor的方法locateExtension完成扩展点的查找最终执行扩展点逻辑
Component
public class ExtensionExecutor extends AbstractComponentExecutor {private static final String EXTENSION_NOT_FOUND extension_not_found;private Logger logger LoggerFactory.getLogger(ExtensionExecutor.class);Resourceprivate ExtensionRepository extensionRepository;Overrideprotected C C locateComponent(ClassC targetClz, BizScenario bizScenario) {C extension locateExtension(targetClz, bizScenario);logger.debug([Located Extension]: extension.getClass().getSimpleName());return extension;}/*** if the bizScenarioUniqueIdentity is ali.tmall.supermarket* p* the search path is as below:* 1、first try to get extension by ali.tmall.supermarket, if get, return it.* 2、loop try to get extension by ali.tmall, if get, return it.* 3、loop try to get extension by ali, if get, return it.* 4、if not found, try the default extension** param targetClz*/protected Ext Ext locateExtension(ClassExt targetClz, BizScenario bizScenario) {checkNull(bizScenario);Ext extension;logger.debug(BizScenario in locateExtension is : bizScenario.getUniqueIdentity());// first try with full namespaceextension firstTry(targetClz, bizScenario);if (extension ! null) {return extension;}// second try with default scenarioextension secondTry(targetClz, bizScenario);if (extension ! null) {return extension;}// third try with default use case default scenarioextension defaultUseCaseTry(targetClz, bizScenario);if (extension ! null) {return extension;}String errMessage Can not find extension with ExtensionPoint: targetClz BizScenario: bizScenario.getUniqueIdentity();throw new ExtensionException(EXTENSION_NOT_FOUND, errMessage);}/*** first try with full namespace* p* example: biz1.useCase1.scenario1*/private Ext Ext firstTry(ClassExt targetClz, BizScenario bizScenario) {logger.debug(First trying with bizScenario.getUniqueIdentity());return locate(targetClz.getName(), bizScenario.getUniqueIdentity());}/*** second try with default scenario* p* example: biz1.useCase1.#defaultScenario#*/private Ext Ext secondTry(ClassExt targetClz, BizScenario bizScenario) {logger.debug(Second trying with bizScenario.getIdentityWithDefaultScenario());return locate(targetClz.getName(), bizScenario.getIdentityWithDefaultScenario());}/*** third try with default use case default scenario* p* example: biz1.#defaultUseCase#.#defaultScenario#*/private Ext Ext defaultUseCaseTry(ClassExt targetClz, BizScenario bizScenario) {logger.debug(Third trying with bizScenario.getIdentityWithDefaultUseCase());return locate(targetClz.getName(), bizScenario.getIdentityWithDefaultUseCase());}private Ext Ext locate(String name, String uniqueIdentity) {final Ext ext (Ext) extensionRepository.getExtensionRepo().get(new ExtensionCoordinate(name, uniqueIdentity));return ext;}private void checkNull(BizScenario bizScenario) {if (bizScenario null) {throw new IllegalArgumentException(BizScenario can not be null for extension);}}}