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>
注:service是hivemind里面的一个核心概念,他的含义与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>
注:在这里,我们定义了一个id为IMessageBuilder的service,并通过嵌套的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。