公司的一个项目,觉得这个设计挺有意思的,记录下来,可能日后会用到。
只记录了大概的一些具有代表性的代码,因修改过公司的包名等一些敏感性的关键字,可能class或者Interface有些错误,但不影响理解。
<!--门票类的调用。从这个bean入手理解设计模式 -->
<bean id="aCompanyTicketInvoker" class="com.neil.util.ServiceRebootableProxy"
factory-method="getInstance">
<constructor-arg index="0"
ref="servicesRebootable" />
<constructor-arg index="1">
<value>com.neil.ticket.ACompanyTicketInvoker</value>
</constructor-arg>
</bean>
<bean id="bCompanyTicketInvoker" class="com.neil.util.ServiceRebootableProxy"
factory-method="getInstance">
<constructor-arg index="0"
ref="servicesRebootable" />
<constructor-arg index="1">
<value>com.neil.ticket.BCompanyTicketInvoker</value>
</constructor-arg>
</bean>
package com.neil;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ServiceRebootableProxy implements InvocationHandler {
private ServiceRebootable serviceRebootable;
private Class targetClass;
public void setServiceRebootable(ServiceRebootable serviceRebootable) {
this.serviceRebootable = serviceRebootable;
}
public void setTargetClass(Class targetClass) {
this.targetClass = targetClass;
}
public static <T> T getInstance(ServiceRebootable rebootable, Class<T> targetClass) {
ServiceRebootableProxy proxy = new ServiceRebootableProxy();
proxy.setServiceRebootable(rebootable);
proxy.setTargetClass(targetClass);
Class[] interfaces = null;
if (targetClass.isInterface()) {
interfaces = new Class[] { targetClass };
} else {
interfaces = targetClass.getInterfaces();
}
return (T) Proxy.newProxyInstance(targetClass.getClassLoader(), interfaces, proxy);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
Object obj = serviceRebootable.get(targetClass);
if (obj == null) {
obj = serviceRebootable.create(targetClass);
}
return method.invoke(obj, args);
} catch (Throwable ex) {
serviceRebootable.destroy(targetClass);
throw ex.getCause();
}
}
}
<bean id="servicesRebootable" class="com.neil.util.CommonServiceRebootable">
<property name="services">
<list>
<bean class="com.neil.ticket.BCompanyTicketInvoker">
<property name="url" value="${BCompany.url}" />
<property name="username" value="${BCompany.username}"/>
<property name="password" value="${BCompany.password}"/>
</bean>
<bean class="com.neil.ticket.ACompanyTicketInvoker">
<property name="agentId" value="${ACompany.agentId}"/>
<property name="secretAuthenticationKey" value="${ACompany.secretAuthenticationKey}"/>
<property name="providerDomainName" value="${ACompany.providerDomainName}"/>
</bean>
</list>
</property>
</bean>
==========================================
package com.neil.util;
public interface ServiceRebootable {
Object get(Class clazz);
Object create(Class clazz);
void destroy(Class clazz);
}
==========================================
package com.neil.util;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class CommonServiceRebootable implements ServiceRebootable {
private Map<Class, Object> serviceMap = Collections.synchronizedMap(new HashMap<Class, Object>());
private List<Initializable> services;
private Logger log = LoggerFactory.getLogger(this.getClass());
public void setServices(List<Initializable> services) {
this.services = services;
}
public Object create(Class clazz) {
Initializable s = find(clazz);
s.init();
serviceMap.put(clazz, s);
log.info(s.getClass().getCanonicalName() + "创建");
return s;
}
public void destroy(Class clazz) {
Initializable s = (Initializable) serviceMap.remove(clazz);
if (s != null) {
s.destroy();
log.info(s.getClass().getCanonicalName() + "销毁");
}
}
public Object get(Class clazz) {
return serviceMap.get(clazz);
}
private Initializable find(Class clazz) {
for (Initializable s : services) {
if (s.getClass().equals(clazz)) {
return s;
}
}
log.error("找不到类" + clazz + "的实例");
return null;
}
}
==========================================
package com.neil.ticket;
public class ACompanyTicketInvoker extends AbstractTicketInvoker implements TicketInvoker, Initializable {
private Logger log = LoggerFactory.getLogger(this.getClass());
private String agentId;
private String secretAuthenticationKey;
private String providerDomainName;
public void init() {
}
/**
* 预订
*/
public OrderResult buy(List<OrderParam> params) throws ServiceException {
//....
return orderResult;
}
/**
* 订单取消
*/
public BaseResult cancel(TicketRecord ticketRecord) throws ServiceException {
//....
return baseResult;
}
/**
* 订单状态查询
*/
public QueryOrderResult queryOrder(TicketRecord ticketRecord) throws ServiceException {
//....
return queryOrderResult;
}
public String getProvider() {
return "ACompany";
}
public void destroy() {
}
public String getAgentId() {
return agentId;
}
public void setAgentId(String agentId) {
this.agentId = agentId;
}
public String getSecretAuthenticationKey() {
return secretAuthenticationKey;
}
public void setSecretAuthenticationKey(String secretAuthenticationKey) {
this.secretAuthenticationKey = secretAuthenticationKey;
}
public String getProviderDomainName() {
return providerDomainName;
}
public void setProviderDomainName(String providerDomainName) {
this.providerDomainName = providerDomainName;
}
}
==========================================
package com.neil.ticket;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public abstract class AbstractTicketInvoker implements TicketInvoker {
private Map<String, AdditionalMethod> methods = new HashMap<String, AdditionalMethod>();
public abstract OrderResult buy(List<OrderParam> params) throws ServiceException;
public abstract BaseResult cancel(TicketRecord ticketRecord) throws ServiceException;
public abstract String getProvider();
public abstract QueryOrderResult queryOrder(TicketRecord ticketRecord) throws ServiceException;
public Object query(String methodName, Object[] args) throws ServiceException {
AdditionalMethod method = methods.get(methodName);
if (method == null) {
throw new ServiceException("没有这个方法: " + methodName);
}
return method.execute(args);
}
public void registerMethod(String name, AdditionalMethod method) {
methods.put(name, method);
}
}
==========================================
package com.neil.util;
public interface Initializable {
void init();
void destroy();
}
==========================================
package com.neil.ticket;
import java.util.List;
public interface TicketInvoker {
String getProvider();
OrderResult buy(List<OrderParam> params) throws ServiceException;
BaseResult cancel(TicketRecord ticketRecord) throws ServiceException;
QueryOrderResult queryOrder(TicketRecord ticketRecord) throws ServiceException;
Object query(String method, Object[] args) throws ServiceException;
BaseResult resendVoucher(TicketRecord ticketRecord) throws ServiceException;
}