版权声明:本文为博主原创文章,欢迎转载。 https://blog.csdn.net/guo_xl/article/details/84111835
1.刚开始的版本
需求是监听user.queue,获取到用户的消息,消息里有用户的增删改操作
做法比较简单使用简单工厂,代码如下
@JmsListener(destination="USER.QUEUE")
public void onMessage(Object message){
if(message instanceof JMSObjectMessage){
JMSObjectMessage msgObj = (JMSObjectMessage)message;
Object payload = msgObj.getObject();
UserMessageHandlerFactory.getHandler(payload).process((PendingUserValue)payload);
}
}
public class UserMessageHandlerFactory{
public static MessageHandler getHandler(PendingUserValue payload){
...
if(payload.getAction()==RequestType.CREATE_USER.getStatusCode()){
return new UserCreateHandler();
}else if(payload.getAction()==RequestType.CREATE_USER.getStatusCode()){
return new UserEditHandler();
}
...
}
}
public static enum RequestType {
CREATE_USER("create_user", 0),
EDIT_USER("edit_user", 1),
DELETE_USER("delete_user", 2);
String statusName;
int statusCode;
RequestType(String statusName, int statusCode) {
this.statusName=statusName;
this.statusCode = statusCode;
}
public String getStatusName() {
return statusName;
}
public int getStatusCode() {
return statusCode;
}
public static RequestType valueOf(int code){
EnumSet<RequestType> set =EnumSet.allOf(RequestType.class);
return set.stream().filter(requestType->{
return requestType.getStatusCode()==code;
}).findFirst().get();
}
}
interface MessageHandler<T>{
public void process(T t) throws Exception;
}
public class UserCreateHandler implements MessageHandler<PendingUserValue>{
public void process(PendingUserValue p){
...
}
}
public class UserEditHandler implements MessageHandler<PendingUserValue>{
public void process(PendingUserValue p){
...
}
}
UML图如下
2. 二期版本
1期开发完毕后,加入了更多的需求,例如account的增删改 ,都是走同样的模式。在1期开发完毕的基础上变成如下模式。由简单工厂变成了工厂方法
public MessageHandlerFactory{
public static MessageHandler getHandler(Object payload){
if(payload instanceOf PendingUserValue){
return UserMessageHandlerFactory.getHandler(PendingUserValue(payload));
}else if(payload instanceOf PendingAccountValue){
return AccountMessageHandlerFactory.getHandler(PendingAccountValue(payload));
}
....
}
}
public class AccountMessageHandlerFactory{
public static MessageHandler getHandler(PendingAccountValue payload){
...
if(payload.getAction()==RequestType.CREATE_ACCOUNT.getStatusCode()){
return new AccountCreateHandler();
}else if(payload.getAction()==RequestType.EDIT_ACCOUNT.getStatusCode()){
return new AccountEditHandler();
}
...
}
}
@JmsListener(destination="USER.QUEUE")
public void onMessage(Object message){
if(message instanceof JMSObjectMessage){
JMSObjectMessage msgObj = (JMSObjectMessage)message;
Object payload = msgObj.getObject();
MessageHandlerFactory.getHandler(payload).process(payload);
}
}
@JmsListener(destination="ACCOUNT.QUEUE")
public void onMessage(Object message){
if(message instanceof JMSObjectMessage){
JMSObjectMessage msgObj = (JMSObjectMessage)message;
Object payload = msgObj.getObject();
MessageHandlerFactory.getHandler(payload).process(payload);
}
}
上面实际上演化成了工厂方法,UML图
优点 :符合开闭原则,比如后面要新加个Group的处理,只需要增加
GroupMessageHandlerFactory
以及GroupCreateHandler
和GroupEditHandler
缺点
MessageHandlerFactory
这个类还是要不断的修改加入if…else。如果增加其他的action ,例如delete
,则GroupMessageHandlerFactory
,
UserMessageHandlerFactory
,
AccountMessageHandlerFactory
都需要加入判断。
由此想到了利用annotation编程
增加一个annotation
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface JMSMessageHandler {
Class jmsPayLoad();//指定jms监听到message是哪种class,例如PendingUserValue,PendingAccoutValue
RequestType requestType();//例如指定是CREATE_USER还是CREATE_ACCOUNT
}
public static enum RequestType {
CREATE_USER("create_user", 0),
EDIT_USER("edit_user", 1),
DELETE_USER("delete_user", 2),
CREATE_ACCOUNT("create_account", 4),
EDIT_ACCOUNT("edit_account", 5),
DELETE_ACCOUNT("delete_account", 6);
String statusName;
int statusCode;
RequestType(String statusName, int statusCode) {
this.statusName=statusName;
this.statusCode = statusCode;
}
public String getStatusName() {
return statusName;
}
public int getStatusCode() {
return statusCode;
}
public static RequestType valueOf(int code){
EnumSet<RequestType> set =EnumSet.allOf(RequestType.class);
return set.stream().filter(requestType->{
return requestType.getStatusCode()==code;
}).findFirst().get();
}
}
@Service
public class MQListenerJMSHandlerDispatcher implements ApplicationContextAware{
private ApplicationContext context;
public void process(Object payload){
//找到所有MessageHandler的bean
Map<String, MessageHandler> msp =BeanFactoryUtils.beansOfTypeIncludingAncestors(context,MessageHandler.class);
try {
msp.values().stream().filter(handler->{
if(!handler.getClass().isAnnotationPresent(JMSMessageHandler.class))
return false;
//找到对应的annotation
JMSHandler[] jmsHandlers = handler.getClass().getAnnotationsByType(JMSMessageHandler.class);
JMSHandler jmsHandler =jmsHandlers[0];
Class payloadClass = jmsHandler.jmsPayLoad();
RequestType choiceType = jmsHandler.requestType();
Base base =(Base)payload;
RequestType requestType = RequestType.valueOf(base.getRequestType());
return base.getClass().isAssignableFrom(payloadClass) &&
requestType==choiceType;
}).findFirst().get().process(payload);
} catch (Exception e) {
e.printStackTrace();
}
}
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context=applicationContext;
}
}
@JMSMessageHandler(jmsPayLoad=PendingUserValue.class,
requestType=RequestType.CREATE_USER)
public class UserCreateHandler implements MessageHandler<PendingUserValue>{
public void process(PendingUserValue p){
...
}
}
@JMSMessageHandler(jmsPayLoad=PendingUserValue.class,
requestType=RequestType.EDIT_USER)
public class UserEditHandler implements MessageHandler<PendingUserValue>{
public void process(PendingUserValue p){
...
}
}
@JMSMessageHandler(jmsPayLoad=PendingAccountValue.class,
requestType=RequestType.CREATE_ACCOUNT)
public class UserCreateHandler implements MessageHandler<PendingAccountValue>{
public void process(PendingAccountValue p){
...
}
}
@JMSMessageHandler(jmsPayLoad=PendingAccountValue.class,
requestType=RequestType.EDIT_ACCOUNT)
public class UserEditHandler implements MessageHandler<PendingAccountValue>{
public void process(PendingAccountValue p){
...
}
}
UML图
优点 : 彻底做到了开闭原则,如果要加入新的handler,只需编写后加入
@JMSMessageHandler
扫描二维码关注公众号,回复: 6396890 查看本文章
参考
简单工厂,工厂模式,抽象工厂笔记