# 消除代码中的if(二)
通过消除代码中的if(一), 我也发现了缺点:如果 if 的条件很多,那么就需要创建很多个Class类来实现 IConsumerHandler ,这样代码不够简洁。(思路借鉴了XXL-JOB的源码)
当我们看到 KafkaListener 注解的实现方式以后,也可以按照它的方式进一步优化。
一个类中,通过方法上的注解,完成 if - else 的简化。
实现原理代码
# 定义个方法上的新注解@RocketmqListener (opens new window)
注解作用在方法上
/**
* 事件监听 - 方法
*
* @author : zhangquansheng
* @date : 2020/4/15 16:09
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface RocketmqListener {
String[] tags() default {};
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# 消费者工厂ConsumerFactory (opens new window)
增加 initConsumerHandlerMethodRepository
用于初始化RocketmqListener
注解的方法,然后根据当前bean
那么和方法名,动态生成对应的class
(这里就是简化类的数量的核心逻辑)
/**
* 消费者工厂
*
* @author : quansheng.zhang
* @date : 2019/8/13 0:21
*/
@Slf4j
public class ConsumerFactory implements ApplicationContextAware {
@Autowired
private ApplicationContext applicationContext;
public static Map<String, Class<IConsumerHandler>> consumerHandlerBeanMap = Maps.newConcurrentMap();
/**
* 获取实体
*
* @param event 事件
* @return IConsumerHandler
*/
public IConsumerHandler create(String event) {
Class<IConsumerHandler> consumerHandlerClass = consumerHandlerBeanMap.get(event);
if (consumerHandlerClass == null) {
return null;
}
return applicationContext.getBean(consumerHandlerClass);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
// init ConsumerHandler Repository
initConsumerHandlerRepository(applicationContext);
// init ConsumerHandler Repository (for method)
initConsumerHandlerMethodRepository(applicationContext);
}
private void initConsumerHandlerRepository(ApplicationContext applicationContext) {
if (applicationContext == null) {
return;
}
Map<String, Object> evenMap = applicationContext.getBeansWithAnnotation(Event.class);
evenMap.forEach((k, v) -> {
Class<IConsumerHandler> consumerHandlerClass = (Class<IConsumerHandler>) v.getClass();
for (String tag : consumerHandlerClass.getAnnotation(Event.class).tags()) {
consumerHandlerBeanMap.put(tag, consumerHandlerClass);
}
});
}
private void initConsumerHandlerMethodRepository(ApplicationContext applicationContext) {
if (applicationContext == null) {
return;
}
// init consumer handler from method
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
Object bean = applicationContext.getBean(beanDefinitionName);
Method[] methods = bean.getClass().getDeclaredMethods();
for (Method method : methods) {
RocketmqListener rocketmqListener = AnnotationUtils.findAnnotation(method, RocketmqListener.class);
if (rocketmqListener != null) {
// tags
String[] tags = rocketmqListener.tags();
if (tags.length == 0) {
throw new RuntimeException("rocketmq-listener method-consumerHandler name invalid, for[" + bean.getClass() + "#" + method.getName() + "] .");
}
for (String tag : tags) {
if (consumerHandlerBeanMap.get(tag) != null) {
throw new RuntimeException("rocketmq-listener consumerHandler[" + tag + "] naming conflicts.");
}
}
// execute method
if (!(method.getParameterTypes() != null && method.getParameterTypes().length == 1 && method.getParameterTypes()[0].isAssignableFrom(String.class))) {
throw new RuntimeException("rocketmq-listener method-consumerHandler param-class-type invalid, for[" + bean.getClass() + "#" + method.getName() + "] , " +
"The correct method format like \" public Action execute(String param) \" .");
}
if (!method.getReturnType().isAssignableFrom(Action.class)) {
throw new RuntimeException("rocketmq-listener method-consumerHandler return-class-type invalid, for[" + bean.getClass() + "#" + method.getName() + "] , " +
"The correct method format like \" public Action execute(String param) \" .");
}
method.setAccessible(true);
for (String tag : tags) {
consumerHandlerBeanMap.put(tag, (Class<IConsumerHandler>) new MethodConsumerHandler(bean, method).getClass());
}
}
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# 方法 消费者处理MethodConsumerHandler (opens new window)
方法消费者处理者,实现IConsumerHandler
,通过反射找到对应的方法
/**
* 方法 消费者处理
*
* @author : zhangquansheng
* @date : 2020/4/15 16:31
*/
@Slf4j
public class MethodConsumerHandler implements IConsumerHandler {
private final Object target;
private final Method method;
public MethodConsumerHandler(Object target, Method method) {
this.target = target;
this.method = method;
}
@Override
public Action execute(String body) {
try {
return (Action) method.invoke(target, new Object[]{body});
} catch (Exception e) {
log.error("method:[{}],body:[{}],execute exception:[{}]", method, body, e.getMessage(), e);
return Action.ReconsumeLater;
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
总结
通过以上的注解,可以大量的减少类的数量,推荐使用此注解。
← 消除代码中的if(一) 💯 动态代理的实现 →