Skip to content

JPlugin扩展开发

sunlet edited this page May 13, 2022 · 14 revisions

处理你自定义对象当中的RefXXX的引用关系

对于Jplugin框架创建的Bean,系统启动时会自动处理RefXXX引用关系,自动为属性赋值。对于开发者自己new出来的对象,默认不会自动为属性赋值。如果希望处理RefXXX标注,执行以下操作:

PluginEnvirement.getInstance().resolveRefAnnotation(object);

注意:在启动阶段,这个调用完毕以后相关Ref不会立即生效,但是后续会自动把值赋好。

增加自定义的@RefXXX支持

如果想增加一种@RefXXX标记,用以自动对属性赋值,比如:想在JPlugin增加Spring的@AutoWire支持

  • 步骤一:先写一个自己的标注类 RefABC(可以按需要命名)

  • 步骤二:写一个实现类实现IAnnoForAttrHandler 接口,泛型是标注类。比如:下面是RefService的实现:

      public class ServiceAttrAnnoHandler implements IAnnoForAttrHandler<RefService> {
      
      	public static IServiceExtensionResolver serviceExtensionResolver;
      
      	public Class<RefService> getAnnoClass() {
      		return RefService.class;
      	}
      
      	public Class getAttrClass() {
      		return Object.class;
      	}
      
      	/**
      	 * 先查找RuleService,再查找Service
      	 */
      	public Object getValue(Object theObject, Class fieldType, RefService anno) {
      		Object o=null;
      		try {
      			// 发生查找错误,不要抛出异常,后续查找
      			if (serviceExtensionResolver != null) {
      				o = serviceExtensionResolver.resolve(theObject, fieldType, anno);
      			}
      		} catch (RuntimeException e) {
      			o = null;
      		}
      		
      		if (o == null){
      			o = get(fieldType,anno);
      		}
      		return o;
      	}
      
      	private Object get(Class fieldType, RefService anno) {
      
      		if (anno.name().equals(""))
      			return ServiceFactory.getService(fieldType);
      		else
      			return ServiceFactory.getService(anno.name(), fieldType);
      
      	}
      }
    
      补充说明:如果有必要可以实现接口的 另一个defualt方法 default Object  getValue(Object theObject,Class fieldType,Field f, T anno) ,可以获取到的信息更多一些。
    
  • 步骤三:在Plugin的构造函数当中,加入下面一句:

      public Plugin(){
          ...
          ExtensionKernelHelper.addAnnoAttrHandlerExtension(this, 步骤一的类名.class);
          ...
      }
    

增加扩展的对象Resolver

需要对容器管理的对象属性自动赋值,尽量用上面的方法“增加自定义的@RefXXX支持”,这样是最方便性能也最佳方式。特殊情况下,也可以增加一个Resolver,方法是在系统启动过程尽早调用以下方法:

PluginEnvirement.getInstance().addObjectResolver(IObjectResolver r);

利用JPlugin的两阶段启动和其他系统集成

和其他容器集成时,JPlugin的启动可以分成两阶段进行:第一阶段准备好所有JPlugin管理的扩展对象;第二阶段进行初始化。
比如和Spring集成,启动步骤可以按照如下规划:

步骤1:启动JPlugin的步骤1
    
    PluginEnvirement.getInstance().startup(null,PluginEnvirement.STARTTYPE_FIRST)

步骤2:初始化spring beans
    ......
    
步骤3:启动JPlugin步骤2

    PluginEnvirement.getInstance().startup(null,PluginEnvirement.STARTTYPE_SECOND)

增加方法级的标注支持

有时候我们希望在JPlugin扩展实例上增加方法级的标注支持,比如对方法加锁@Lock。 这类需求可以通过Extension拦截器来实现ExtensionInterceptor。

假如你想增加标注@Lock

步骤一:先写一个@Lock的标注类,这步省略了

步骤二:注册一个拦截器扩展,可以在Plugin.java构造函数加入

  public class Plugin{
     public Plugin(){ 

           ExtensionKernelHelper.addExtensionInterceptorExtension(this, LockIncept.class,null,EP_SERVICE,null,null , Lock.class);

        //xxxxxxx
   }
  }

 步骤三:步骤二当中LockIncept的实现代码

    public class LockInceptextends AbstractExtensionInterceptor {

        @Override
        protected Object execute(FilterChain fc, ExtensionInterceptorContext ctx) throws Throwable {
          try{
            getYourLock();
            //拦截方法的操作可以从ctx当中获取到当前执行的方法等上下文信息
            return fc.next(ctx)
          }finally{
            releaseYourLock();
          }
        }
    }