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。

Hivemind简介相关推荐

  1. c语言中ioc有什么作用,IOC简介

    一.IOC简介 IOC-全称Inversion of Control,中文解释:控制反转.另外,IOC又称DI(全称)Dependency Injection,中文解释:依赖注入. 呵呵,这些名词搞得 ...

  2. java开源工具简介(2)

    java开源工具简介(2) OpenCms [Java开源 CMS系统] OpenCms是一个J2EE的产品,它是用Java写成的.它和Tomcat捆绑在一起.但是也能够使用ATG Dynamo.We ...

  3. etcd 笔记(01)— etcd 简介、特点、应用场景、常用术语、分布式 CAP 理论、分布式原理

    1. etcd 简介 etcd 官网定义: A highly-available key value store for shared configuration and service discov ...

  4. Docker学习(一)-----Docker简介与安装

    一.Docker介绍 1.1什么是docker Docker是一个开源的应用容器引擎,基于Go语言并遵从Apache2.0协议开源 Docker可以让开发者打包他们的应用以及依赖包到一个轻量级,可移植 ...

  5. 【Spring】框架简介

    [Spring]框架简介 Spring是什么 Spring是分层的Java SE/EE应用full-stack轻量级开源框架,以IOC(Inverse Of Control:反转控制)和AOP(Asp ...

  6. TensorRT简介

    TensorRT 介绍 引用:https://arleyzhang.github.io/articles/7f4b25ce/ 1 简介 TensorRT是一个高性能的深度学习推理(Inference) ...

  7. 谷粒商城学习笔记——第一期:项目简介

    一.项目简介 1. 项目背景 市面上有5种常见的电商模式 B2B.B2C.C2B.C2C.O2O B2B 模式(Business to Business),是指商家和商家建立的商业关系.如阿里巴巴 B ...

  8. 通俗易懂的Go协程的引入及GMP模型简介

    本文根据Golang深入理解GPM模型加之自己的理解整理而来 Go协程的引入及GMP模型 一.协程的由来 1. 单进程操作系统 2. 多线程/多进程操作系统 3. 引入协程 二.golang对协程的处 ...

  9. Linux 交叉编译简介

    Linux 交叉编译简介 主机,目标,交叉编译器 主机与目标 编译器是将源代码转换为可执行代码的程序.像所有程序一样,编译器运行在特定类型的计算机上,输出的新程序也运行在特定类型的计算机上. 运行编译 ...

最新文章

  1. 编译android不再需要jdk1.5
  2. bigdecimal为0 xml不走_爱情不能够接受谎言的星座,天蝎座容忍度为0,发现将失去彼此...
  3. springMVC之Interceptor拦截器
  4. BC30138: 无法在路径“C:\WINDOWS\TEMP\”中创建临时文件: 拒绝访问。
  5. springboot 与shiro整合
  6. 2021年中国地下采矿机械市场趋势报告、技术动态创新及2027年市场预测
  7. String类两种实例化方式的区别
  8. 如何用一台计算机控制多台计算机,怎么用一套鼠标键盘操作两台或多台电脑?...
  9. 聚类分析原理及R语言实现过程
  10. angular对象简单介绍
  11. 在线QQ客服链接,只添加 qq号
  12. 【C】狐狸找兔子问题
  13. CentOS6安装rpm时报错“Cannot find a valid baseurl for repo: centos-sclo-rh“的解决办法
  14. jQuery读取JSON数据(jQuery调用JSON数据学习第二天)
  15. 基于CST相控阵天线快速设计方法
  16. PS字体加粗的小方法、、
  17. win32游戏开发(2) --连连看游戏制作(vc++版)
  18. PCB如何入门---一些经验与教训
  19. 雕刻效果的实现【OpenCV+QT】
  20. prescan安装包(8.5/2019.2版本)下载

热门文章

  1. parent()与parents()的区别
  2. 由Github迁移到GitCafe
  3. gitcafe: programming everyday
  4. 2014秋C++ 狗逮耗子之“开口说英语”
  5. 因式分解法解一元二次方程
  6. html字母显示红色,css中字体红色如何实现?
  7. YoloV5+ROS2直接发布出物品坐标
  8. 系统服务器 lis6.0,LIS系统条形码生成接口说明(Service)
  9. 硬件知识:32-64位电脑?操作系统?软件?
  10. Altium Allegro PADS到底该选哪个EDA设计软件