ActiveMQ中使用了大量的工厂模式和反射模式,下面通过ActiveMQConnectionFactory创建connection来理解一下。
ActiveMQ实现了JMS1.1规范,同样ActiveMQConnectionFactory也是如此,客户端可以通过如下步骤来创建一个Connection:
String url = “tcp://localhost:61616”;
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(url);
Connection conn = connectionFactory.createConnection();
createConnection需要如下的几个操作:
Transport transport = createTransport();
Connection = createActivemqConnection(transport,factoryStats);
configureConnection(connection);
transport.start();
原来真正的创建socket连接是在createTransport()中实现的。
调用TransportFactory.connect(brokerURL, DEFAULT_CONNECTION_EXECUTOR);
TcpTransportFactory FactoryFinder TransportFactory findTransportFactory URI Executor Transport URI Executor Transport TcpTransportFactory FactoryFinder TransportFactory findTransportFactory URI Executor Transport TcpTransportFactory FactoryFinder TransportFactory findTransportFactory URI Executor Transport TcpTransportFactory FactoryFinder TransportFactory findTransportFactory URI Executor Transport TcpTransportFactory FactoryFinder TransportFactory findTransportFactory URI Executor Transport TcpTransportFactory FactoryFinder TransportFactory findTransportFactory URI Executor Transport TcpTransportFactory FactoryFinder TransportFactory findTransportFactory URI Executor Transport
图一
如图一所示TransportFactory根据输入URI,Executor 生产Transport。TransportFactory中的findTransportFactory方法调用辅助类FactoryFinder根据scheme选择合适的TransportFactory,这里选择的是TcpTransportFactory来生产Transport。这里TransportFactory当了一个工厂代理的角色。
TcpTransportFactory继承了TransportFactory。其UML图如下:
图二
FactoryFinder类的目的是根据scheme来生产合适的TransportFactory。生产过程如下:
public Object newInstance(String key, String propertyPrefix) throws IllegalAccessException, InstantiationException, IOException, ClassNotFoundException {
if (propertyPrefix == null) {
propertyPrefix = "";
}
Class clazz = classMap.get(propertyPrefix + key);
if (clazz == null) {
clazz = newInstance(doFindFactoryProperies(key), propertyPrefix);
classMap.put(propertyPrefix + key, clazz);
}
return clazz.newInstance();
}
首先从缓存classMap中去取,如果没有再生成一个新的实例并放入到缓存中。doFindFactoryProperies(key)负责将外部properties文件读入
private Properties doFindFactoryProperies(String key) throws IOException {
String uri = path + key;
// lets try the thread context class loader first
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if (classLoader == null) {
classLoader = getClass().getClassLoader();
}
InputStream in = classLoader.getResourceAsStream(uri);
if (in == null) {
in = FactoryFinder.class.getClassLoader().getResourceAsStream(uri);
if (in == null) {
throw new IOException("Could not find factory class for resource: " + uri);
}
}
// lets load the file
BufferedInputStream reader = null;
try {
reader = new BufferedInputStream(in);
Properties properties = new Properties();
properties.load(reader);
return properties;
} finally {
try {
reader.close();
} catch (Exception e) {
}
}
}
外部文件的内容(MeTA-INF/services/org/apache/activemq/transport/tcp):class=org.apache.activemq.transport.tcp.TcpTransportFactory
然后利用反射来生成类org.apache.activemq.transport.tcp.TcpTransportFactory的实例。
如下:
private Class newInstance(Properties properties, String propertyPrefix) throws ClassNotFoundException, IOException {
String className = properties.getProperty(propertyPrefix + "class");
if (className == null) {
throw new IOException("Expected property is missing: " + propertyPrefix + "class");
}
Class clazz = null;
ClassLoader loader = Thread.currentThread().getContextClassLoader();
if (loader != null) {
try {
clazz = loader.loadClass(className);
} catch (ClassNotFoundException e) {
// ignore
}
}
if (clazz == null) {
clazz = FactoryFinder.class.getClassLoader().loadClass(className);
}
return clazz;