java - Spring中基于自定义注解的方法调用?

标签 java spring spring-mvc spring-annotations java-annotations

我有一个自定义注释:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Controller {
    EventType[] events() default EventType.MESSAGE;
}

B 类中有一些方法使用它们,如下所示:

@Controller(events = {EventType.MESSAGE, EventType.DIRECT_MESSAGE})
public void onMessage(Message msg) {    }

@Controller(events = {EventType.STAR_ADDED})
public void onStarAdded(Message msg) {    }

现在,我想根据另一个类A的注释events值调用上述方法。换句话说,当类 A 接收到 STAR_ADDED 类型的事件时,我想使用注释 @ 调用类 B 中的所有方法 Controller (事件= {EventType.STAR_ADDED})

我知道如何在 Java 中执行此操作,但是 Spring 是否提供任何 API 来执行此操作?如果是,代码片段也会有帮助。

最佳答案

解决方案 1:

你也可以这样做:

enum EventType {
    MESSAGE {
        @Override
        public void handleMessage(Service service, Message message) {
            service.onMessage(message);
        }
    },
    STAR_ADDED {
        @Override
        public void handleMessage(Service service, Message message) {
            service.onStarAdded(message);
        }

        public abstract void handleMessage(Service service, Message message);
    }
}

在您的其他类(class)中,您知道什么是“Activity ”事件:

yourEvent.handleMessage(service, message);

解决方案 2:

我不知道spring是否有专门的功能,否则你也可以使用反射。这是一个使用反射的示例(我更喜欢上面的解决方案=>不带反射的枚举):

for(Method method: Service.class.getDeclaredMethods()){
    Controller annotation = m.getAnnotation(Controller.class);
    for(EventType event: annotation.events()){
        if(event.equals(yourActiveEventType)){
            method.invoke(service, message);
        }
        return ...
    }
}

提示(不是解决方案)3:

我真的不认为以下内容适用于您的场景,但我想我会提到它...Spring AOP 允许您在调用带注释的方法时触发一些代码(这与您的场景相反) ,检查这个答案,但它可能值得您阅读:aspectj-pointcut-for-all-methods-of-a-class-with-specific-annotation

@Around("execution(@Controller * com.exemple.YourService.*(..))")
public Object aroundServiceMethodAdvice(final ProceedingJoinPoint pjp)
   throws Throwable {
   // perform actions before

   return pjp.proceed();

   // perform actions after
}

解决方案4:(在评论后添加)

使用 org.reflections

<dependency>
    <groupId>org.reflections</groupId>
    <artifactId>reflections</artifactId>
    <version>0.9.10</version>
</dependency>

示例:

Service service = ...;
Message message = ...;

Set<Method> methods = 
        ReflectionUtils.getMethods(Service.class, ReflectionUtils.withAnnotation(Controller.class),ReflectionUtils.withParametersAssignableTo(Message.class));

for(Method m: methods){
    Controller controller = m.getAnnotation(Controller.class);
    for(EventType eventType: controller.value()){
        if(EventType.MESSAGE.equals(eventType)){
            m.invoke(service, message);
        }
    }
}

这假设您已经持有对 Service 对象(您的方法所在)的引用。

由于您使用的是Spring,如果您的“服务”是由spring管理的,您可能会从spring的上下文中获取实例,您必须自己尝试一下,因为这在某种程度上与您的设计有关:

@Autowired
private ApplicationContext appContext;

Reflections r  = new Reflections(new MethodAnnotationsScanner(), "com.your.package");
Set<Method> methods = r.getMethodsAnnotatedWith(Controller.class);
for(Method m: methods){
    Controller controller = m.getAnnotation(Controller.class);
    for(EventType eventType: controller.value()){
        if(EventType.MESSAGE.equals(eventType)){
            String className = m.getDeclaringClass().getSimpleName();
            className = className.replaceFirst(className.substring(0,1), className.substring(0,1).toLowerCase());
            Object service = appContext.getBean(className);
            m.invoke(service, message);
        }
    }
}

如果您的类是 spring 管理的,并且使用其默认的驼峰名称添加到上下文中,则此方法有效。

你可以简化逻辑,但我相信主要要素就在那里。

关于java - Spring中基于自定义注解的方法调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37775099/

相关文章:

java - Hibernate/Spring - JUnit 因事务而失败(REQUIRES_NEW)

Spring 5 - 没有 ServletContext 设置异常

java - 使用 Spring Web MVC validator 类的服务器端验证

java - Spring MVC,Tile在运行war文件jetty Runner时不渲染jsp页面

java - 在 Java 中查找一组值中的模式

java - 直接在 JBoss 服务器上配置 javax.faces.FACELETS_REFRESH_PERIOD

spring - Rest Template 自定义异常处理

java - 为 Spring MVC Controller - AOP 或 Spring Security 的方法传递密码?

java - 尝试用java制作文字冒险。但我的互动被窃听了

java - Spring Cloud Config Server - 连接 github 的用户名和密码