Java 如何在运行时更改方法注释值?
我有一个控制器Java 如何在运行时更改方法注释值?,java,reflection,annotations,aop,Java,Reflection,Annotations,Aop,我有一个控制器 @MessageMapping("/room.register") @SendTo("#{sendTo}") public Message addUser(@Payload Message message, SimpMessageHeaderAccessor headerAccessor) { headerAccessor.getSessionAttributes().put("username", message.
@MessageMapping("/room.register")
@SendTo("#{sendTo}")
public Message addUser(@Payload Message message,
SimpMessageHeaderAccessor headerAccessor) {
headerAccessor.getSessionAttributes().put("username",
message.getSender());
return message;
}
我想在运行时更改SendTo注释的值
我试着这样做:
@Aspect
public class SendToAspect {
@Autowired
private WebSocketConfigurationProperties webSocketConfigurationProperties;
@Around("execution (public * *(..)) && @annotation(ann)")
public Object execute(final ProceedingJoinPoint point, final SendTo ann)
throws Throwable {
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
method.setAccessible(true);
Annotation[] annotations = method.getDeclaredAnnotations();
for (int i = 0; i < annotations.length; i++) {
if (annotations[i].annotationType().equals(SendTo.class)) {
annotations[i] = new SendTo() {
@Override
public Class<? extends Annotation> annotationType() {
return SendTo.class;
}
@Override
public String[] value() {
return new String[]
{webSocketConfigurationProperties.getTopic()};
}
};
}
}
return point.proceed();
}
}
@方面
公共类SendToAspect{
@自动连线
私有WebSocketConfigurationProperties WebSocketConfigurationProperties;
@关于(“执行(公共**(..)&&&@注释(ann)”)
公共对象执行(最终过程连接点,最终发送到ann)
扔掉的{
MethodSignature=(MethodSignature)point.getSignature();
Method=signature.getMethod();
方法setAccessible(true);
Annotation[]annotations=method.getDeclaredAnnotations();
for(int i=0;i
你可能想调查一下
- 对于
@SendTo
或@SubscribeMapping
以及
- 我的答案是关于如何做
也许这两种方法中的一种对你来说是可行的
话虽如此,您也可以转向原力的黑暗面,真正尝试操纵注释值
示例驱动程序应用程序:
package de.scrum\u master.app;
导入org.springframework.messaging.handler.annotation.SendTo;
公共类应用程序{
@发送至(“原件”)
public void doSomething()抛出NoSuchMethodException、SecurityException{
SendTo SendTo=Application.class
.getDeclaredMethod(“doSomething”)
.getAnnotationsByType(SendTo.class)[0];
System.out.println(sendTo.value()[0]);
}
公共静态void main(字符串[]args)抛出NoSuchMethodException、SecurityException{
新应用程序().doSomething();
新应用程序().doSomething();
新应用程序().doSomething();
}
}
如果没有方面,这将打印:
原件
起初的
起初的
这里没有什么奇怪的。现在使用这个特性(在SpringAOP中,您还应该添加一个@组件
注释):
package de.scrum\u master.aspect;
导入java.lang.annotation.annotation;
导入java.lang.reflect.Field;
导入java.lang.reflect.Proxy;
导入java.util.Map;
导入org.aspectj.lang.JoinPoint;
导入org.aspectj.lang.annotation.Aspect;
导入org.aspectj.lang.annotation.Before;
导入org.springframework.messaging.handler.annotation.SendTo;
@面貌
公共类SendToAspect{
@在(“执行(**(..)&&&&@注释(发送到)”之前
公共void changeAnnotation(JoinPoint thisJoinPoint,SendTo SendTo){
System.out.println(thisJoinPoint+“\n[之前]”+sendTo);
changeAnnotationValue(sendTo,“value”,新字符串[]{“changed”});
System.out.println(“[之后]”+sendTo);
}
@抑制警告(“未选中”)
公共静态对象changeAnnotationValue(注释注释、字符串键、对象newValue){
对象处理程序=Proxy.getInvocationHandler(注释);
字段f;
试一试{
f=handler.getClass().getDeclaredField(“memberValues”);
}catch(NoSuchFieldException | SecurityException e){
抛出新的非法状态异常(e);
}
f、 setAccessible(true);
映射成员值;
试一试{
memberValues=(Map)f.get(handler);
}捕获(IllegalArgumentException | IllegalAccessException e){
抛出新的非法状态异常(e);
}
对象oldValue=memberValues.get(键);
如果(oldValue==null | | oldValue.getClass()!=newValue.getClass()){
抛出新的IllegalArgumentException();
}
memberValues.put(key,newValue);
返回旧值;
}
}
现在控制台日志是:
执行(void de.scrum\u master.app.Application.doSomething())
[之前]@org.springframework.messaging.handler.annotation.SendTo(值=[原始])
[在]@org.springframework.messaging.handler.annotation.SendTo之后(值=[更改])
改变
执行(void de.scrum\u master.app.Application.doSomething())
[之前]@org.springframework.messaging.handler.annotation.SendTo(值=[更改])
[在]@org.springframework.messaging.handler.annotation.SendTo之后(值=[更改])
改变
执行(void de.scrum\u master.app.Application.doSomething())
[之前]@org.springframework.messaging.handler.annotation.SendTo(值=[更改])
[在]@org.springframework.messaging.handler.annotation.SendTo之后(值=[更改])
改变
正如您在上面的日志中所看到的,如果您只需要更改一次值,并且其值不是动态的,那么每次调用该方法时执行aspect通知是低效的。相反,您也可以从aspect之外的其他位置操纵注释,或者向aspect添加一个静态布尔成员,以便操纵anno只有一次:
static boolean done=false;
@在(“执行(**(..)&&&&@注释(发送到)”之前
公共void changeAnnotation(JoinPoint thisJoinPoint,SendTo SendTo){
如果(完成)
返回;
System.out.println(thisJoinPoint+“\n[之前]”+sendTo);
changeAnnotationValue(sendTo,“value”,新字符串[]{“changed”});
System.out.println(“[之后]”+sendTo);
完成=正确;
}
那么输出将是:
执行(void de.scrum\u master.app.Application.doSomething())
[之前]@org.springframework.messaging.handler.annotation.SendTo(值=[原始])
[在]@org.springframework.messaging.handler.annotation.SendTo之后(值=[更改])
改变
改变
改变
另见:
- 上面我的方面中的项目、助手方法取自
- 顺便说一句,JavaEx的灵感也来自于
注释是在编译时确定的,这就是为什么它们只能包含常量