当前位置: 首页 > 工具软件 > HiveMind > 使用案例 >

Hivemind简介

轩辕嘉平
2023-12-01

1.      一个完整的例子

a)        目录结构

|--

|  |--META-INF

|  |--

|     |--hivemodule.xml

|  |--log4j.properties

|

|--nick

|--Test.java

|--IHello.java

|--IMessageBuilder.java

|--impl

    |--HelloImpl.java

    |--MessageBuilderImpl.java

 

b)        Hivemodule.xml

<?xml version="1.0"?>

<module id="nick" version=" 1.0.0 " package="nick">

     <service-point id="IHello" interface="IHello">

         <invoke-factory>

              <construct class="impl.HelloImpl" />

         </invoke-factory>

     </service-point>

 

     <service-point id="IMessageBuilder" interface="IMessageBuilder">

         <create-instance class="impl.MessageBuilderImpl" />

     </service-point>

</module>

 

注:servicehivemind里面的一个核心概念,他的含义与Spring里面的bean类似。这里定义了两个service,我们可以通过<invoke-factory>或者<create-instance>来指定该接口所对应的实现类。这两个标签都是用于指定可实例话的类,他们的区别是,invoke-factory的可配性更多一些,也就是说,他可以更大限度的对实例化过程进行定制。

 

c)        测试类(Test

package nick;

 

/**

 *   @author cenyongh@gmail.com

 */

 

public class Test {

     public static void main(String[] args) {

         Registry registry = RegistryBuilder.constructDefaultRegistry();

         IHello hello = (IHello) registry.getService(IHello.class);

         hello.hello("nick");

     }

}

 

注:这里唯一要留意的就是Hivemind的程序入口是Registry类,上面的代码演示了如何得到一个Registry引用,并且如何从该Registry得到我们想要的事例。

 

d)        自动编织

Hivemind通过setXXX()方法来实现自动的依赖注入。

 

2.      Service Override

有的时候你需要替换掉某个service的默认实现。这可以通过<implementation>来实现。

 

<?xml version="1.0"?>

<module id="nick" version=" 1.0.0 " package="nick">

     <service-point id="IHello" interface="IHello">

         <invoke-factory>

              <construct class="impl.HelloImpl" />

         </invoke-factory>

     </service-point>

 

     <service-point id="IMessageBuilder" interface="IMessageBuilder">

         <create-instance class="impl.MessageBuilderImpl" />

     </service-point>

    

     <implementation service-id="IMessageBuilder">

         <create-instance class="impl.MessageBuilderImpl2"/>

     </implementation>

</module>

 

注:在这里,我们定义了一个idIMessageBuilderservice,并通过嵌套的create-instance标记定义了实现类。但是后续的implementation标签,则通过指定service-id的方式,替换了该默认实现,这样的一个直接后果就是,所有引用IMessageBuilder的地方都将使用impl.MessageBuilderImpl2这个新的实现类。

 

3.      ServiceImplementationFactory

在定义<service>时,我们可以通过<invoke-factory>或者<create-instance>来创建事例。而如果使用<invoke-factory>的话,则可以通过指定一个service-id,来指定某一个ServiceImplementationFactory实例,来负责实例的创建。

a)        Hivemodule.xml

<?xml version="1.0"?>

<module id="nick" version=" 1.0.0 " package="nick">

     <service-point id="myFactory" interface="org.apache.hivemind.ServiceImplementationFactory">

         <create-instance class="MyFactory" />

     </service-point>

 

     <service-point id="IHello" interface="IHello">

         <invoke-factory service-id="myFactory">

              <construct class="impl.HelloImpl" />

         </invoke-factory>

     </service-point>

</module>

 

b)        ServiceImplementationFactory

public class MyFactory implements ServiceImplementationFactory {

  public Object createCoreServiceImplementation(

            ServiceImplementationFactoryParameters arg0) {

       Module module = arg0.getInvokingModule();

 

       ElementImpl para = (ElementImpl) arg0.getFirstParameter();

       Class klass = module.resolveType(para.getAttributeValue("class"));

       try {

            Object inst = klass.newInstance();

            return inst;

       } catch (Exception e) {

            e.printStackTrace();

            return null;

       }

  }

}

 

注:由于我们在module上面定义了module所属的主package,所以在<construct>标签里面,我们的class属性里面并不是类的完整包名。所以,这里需要用module来得到完整的类名。上述方案可以正确的创建实例,但是并没有进行依赖注入。默认情况下,hivemind使用单子模式来创建实例,而单子的管理则不是在ServiceImplementationFactory里实现,而是由外部负责调用ServiceImplementationFactory的类完成。

 

4.      Interceptor

a)        语法:

<service-point id="myInterceptorFactory"

              interface="org.apache.hivemind.ServiceInterceptorFactory">

              <create-instance class="MyInterceptorFactory" />

          </service-point>

 

          <service-point id="IHello" interface="IHello">

               <create-instance class="impl.HelloImpl" />

              <interceptor service-id="myInterceptorFactory" />

</service-point>

 

注:Interceptor也是一个service,它需要实现ServiceInterceptorFactory。通过<interceptor>声明所使用的Interceptor

 

b)        Interceptor实现

public class MyInterceptorFactory implements ServiceInterceptorFactory {

 

     public void createInterceptor(InterceptorStack stack,

              Module invokingModule, List parameters) {

 

         Object inst = stack.peek();

         ClassPool pool = ClassPool.getDefault();

         try {

              CtClass superClass = pool.get(inst.getClass().getCanonicalName());

              CtClass interceptor = pool.makeClass(inst.getClass().getCanonicalName()

                       + "inter");

              interceptor.setSuperclass(superClass);

 

              CtMethod[] methods = superClass.getDeclaredMethods();

              for (CtMethod method : methods) {

                   CtMethod nm = CtNewMethod.copy(method, interceptor, null);

                   interceptor.addMethod(nm);

                   nm.setBody("{System.out.println(/"[BEFORE]" + method.getName()

                            + "/");super." + method.getName()

                            + "($$);System.out.println(/"[AFTER]"

                            + method.getName() + "/");}");

 

              }

              stack.push(interceptor.toClass().newInstance());

         } catch (Exception e) {

              e.printStackTrace();

         }

     }

}

 

注:以上代码我们做了以下几件事。第一我们得到了需要被Intercept的类。然后利用Javassist来创建一个该类的子类。第三,由于我们不一定有被Intercept类的源代码,所以,上述代码所采用的方式是,对被Intercept类的每个声明的方法复制其方法签名,然后通过setBody()方式替换其内部实现。最后,就是把Javassist创建的子类实例化,并压到InterceptorStack当中。上述代码做的就是一个Logger

 
 类似资料: