场景:
实际场景中,我们通常会将一类操作定义为xxxHandler,xxxProcessor。这样,我们需要对handler/processor进行统一管理,类似定义一个工厂,可以从工厂中根据type得到实际的handler/processor。
实现1
我一种常用的实现思路是在 每个handler的bean afterpropertiySet 方法中 regist (this)到一个xxxManager中。Manager中持有一个static的Map
实现2
另一种实现方式是用sofa框架的扩展点(spring原生是否有对应机制?不确定,暂时没查到)
原理:一般sofa下,不同bundle的spring上下文是不同的,独立的,不能互相访问。 sofa 扩展点机制提供了一种能力,可以在一个spring上下文中 修改另一个上下文中bean的属性。(当然,在同一个上下文中修改也是可以的)
定义一个贡献点的描述(通常是一个要修改的bean的属性的类型,比如上面的case,就是Map
@XObject("processor")
public class ProcessorDescriptor {
@XNode("type")
public String type;
@XNode("ref")
public Processor ref;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Processor getRef() {
return ref;
}
public void setRef(Processor ref) {
this.ref = ref;
}
}
定一个一个扩展点
<sofa:extension-point name="taskProcessorExtensionPoint" ref="taskProcessor">
<sofa:object class="com.alipay.antmedia.core.service.upgrade.monitor.processor.ProcessorDescriptor"/>
</sofa:extension-point>
// ref代表是给谁定义扩展点, 就是那个工厂类
// <sofa:object>是定义 贡献点的类型
对定义好的扩展点,进行扩展(这里就好比于,上面只是声明了一个扩展点,这里是对它实例化)
<sofa:extension bean="taskProcessor" point="taskProcessorExtensionPoint">
<sofa:content>
<processor>
<!-- 这里 type ref 对应于 ProcessorDescriptor 中的 @XNode 后面声明的字符串-->
<type>ASSIGN</type>
<ref>ruleAssignerProcessor</ref>
</processor>
</sofa:content>
</sofa:extension>
然后在工厂类中,定义regist 方法
public class TaskProcessor {
private Map<String, Processor> prossors = new HashMap<>();
public void trigger(ProcessContext processContext) {
prossors.get(processContext.getTaskType());
}
/**
* 组件方法,SOFA 框架将会调用这个方法进行扩展点设置,必不可少!
* 只设置了一个贡献点,该方法还比较简单,随着贡献点增多,方法会变复杂。
*/
public void registerExtension(Extension extension) {
Object[] contributions = extension.getContributions();
String extensionPoint = extension.getExtensionPoint();
if ("taskProcessorExtensionPoint".equals(extensionPoint)) {
Arrays.stream(contributions).forEach(contribution -> {
ProcessorDescriptor processorDescriptor = (ProcessorDescriptor)contribution;
prossors.put(processorDescriptor.getType(), processorDescriptor.getRef());
});
}
}
public void setProssors(Map<String, Processor> prossors) {
this.prossors = prossors;
}
对比
实现2的方式,通常属性是非static的,如果要获取,需要通过实例化工厂来获取。而实现1直接static的方式获取