Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何通过@Aspect为字段设置值?_Java_Spring_Aspectj_Spring Aop_Aspect - Fatal编程技术网

Java 如何通过@Aspect为字段设置值?

Java 如何通过@Aspect为字段设置值?,java,spring,aspectj,spring-aop,aspect,Java,Spring,Aspectj,Spring Aop,Aspect,我有一个调用方法的服务。此外,在该服务中还有一个字段,需要通过方面使用自定义注释为其赋值 服务 @Service public class TestServiceImpl implements TestService { @MyAnnotation(value = "someName") private Boolean isActive; @Override public String success(String name) {

我有一个调用方法的服务。此外,在该服务中还有一个字段,需要通过方面使用自定义注释为其赋值

服务

@Service
public class TestServiceImpl implements TestService {
    
    @MyAnnotation(value = "someName")
    private Boolean isActive;

    @Override
    public String success(String name) {
        return (isActive) ? "Yes" : "No";
    }
}
注释

@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = ElementType.FIELD)
public @interface MyAnnotation{
    String value() default "";
}

通过在注释中传递的值,数据库中应该有一条记录具有is_active字段,并且该值应该分配给服务中的isActive字段

如果您希望坚持使用Spring AOP或更灵活的应用程序设计,我还建议您实施另一个应用程序设计。例如,为什么不注释
success(..)
方法,并在
@Around
建议中截取该方法,该建议基于注释值返回数据库配置值

如果您绝对坚持注释字段,您必须同意从Spring AOP切换到,因为AspectJ可以通过
get()
set()
切入点拦截字段读/写访问。但是,如果字段是私有的,则需要特权方面,并且不能使用注释样式语法

下面是我的全部内容,在Spring之外使用AspectJ向您展示了它的基本实现方式:

带有配置键的标记注释:

package de.scrum\u master.app;
导入静态java.lang.annotation.ElementType.FIELD;
导入静态java.lang.annotation.RetentionPolicy.RUNTIME;
导入java.lang.annotation.Retention;
导入java.lang.annotation.Target;
@保留(运行时)
@目标(场)
公共@接口标记{
字符串值()默认为“”;
}
驱动程序应用程序:

package de.scrum\u master.app;
导入java.io.PrintStream;
公共类应用程序{
@标记整数;
@标记(“设置”)专用布尔值为活动;
@标记(“设置B”)私有布尔值是NICE;
公共字符串成功(字符串名称){
return isActive?“是”:“否”;
}
公共字符串nice(字符串名称){
返回是否很好?“是”:“否”;
}
公共静态void main(字符串[]args){
应用程序app=新应用程序();
app.number=11;
PrintStream out=System.out;
out.println(应用程序编号);
out.println(app.success(“foo”));
out.println(app.nice(“bar”);
}
}
方面:

为了更好地理解细节,请阅读评论。建议#1-#4更像是使用
get()
set()
的一般操作教程,最后一条建议(滚动到末尾)就是您在这种特定情况下实际需要的

package de.scrum\u master.aspect;
导入de.scrum_master.app.Application;
导入de.scrum_master.app.Marker;
/**
*请注意“特权”。这仅适用于本机AspectJ语法,请参阅
* https://www.eclipse.org/aspectj/doc/next/adk15notebook/ataspectj-aspects.html:
*“批注样式不支持特权特性。”
*/
公共特权方面MyAspect{
/**
*在字段写访问期间,没有获取旧字段值的通用方法。
*但我们可以通过“args”获取新值,并在继续操作时对其进行操作。
*/
周围为空(int newValue):
设置(@Marker**)和&args(newValue)
{
int newValueUpdated=3*newValue;
System.out.println(thisJoinPoint+“环绕:newV=“+newValue+”->“+newValue更新);
继续(更新新价值);
}
/**
*如果我们确切地知道目标字段,我们当然可以通过绑定
*将实例作为通知参数的目标,或直接访问静态字段。
*但是,如果字段是私有的,则方面必须具有特权。
*/
周围无效(int newValue,应用程序):
set(int Application.number)&&args(newValue)&&target(Application)
{
int oldValue=application.number;
int newValueUpdated=newValue+7;
System.out.println(thisJoinPoint+“大约:”+“oldV=“+oldValue+”,newV=“+newValue+”->“+newValueUpdated);
继续(更新新价值,申请);
}
/**
*在字段读取访问期间,只需继续即可轻松获取旧字段值。
*可以通过从通知返回新值来设置新值。
* 
*“!within(MyAspect)”避免在从此方面读取字段时触发通知。
*/
int around():
在(MyAspect)中获取(@Marker int*)&&&
{
int oldValue=继续();
int newValue=oldValue+1000;
System.out.println(thisJoinPoint+“环绕:”+oldValue+“->”+newValue);
返回新值;
}
/**
*对于仅截取新设置的字段值,可以使用“after()returning”。
*对于这个简单的例子,我们不需要“around()”建议。
*当然,不能在这里设置新值,因为这已经发生了。
* 
*请注意,此建议如何在应用程序中捕获对System.out的访问。
*/
在()返回后(对象newValue):
在(MyAspect)中获取(**)&&
{
System.out.println(RET:+newValue后的thisJoinPoint+);
}
/**
*在更一般的部分之后,这个建议实际上回答了下面的问题
* https://stackoverflow.com/q/66563533/1082681:
* 
*我们寻找带注释的布尔字段(可以轻松调整为其他类型),
*通过“@annotation()”从值绑定中获取注释值,然后
*使用该值从数据库中获取所需的配置值。
*/
布尔值(标记):
获取(@Marker boolean*)&&&!在(MyAspect)&&&&@注释(Marker)
{
System.out.println(thisJoinPoint+“从数据库中获取“+标记+”的配置值”);
返回getConfigValueFromDB(marker.value());
}
/**
*数据库访问模型
*/
私有布尔getConfigValueFromDB(字符串键){
开关(钥匙){
案例“设置A”:返回true;
案例“设置B”:返回false;
默认:返回false;
}
}
}
控制台日志:

set(int de.scrum\u master.app.Application.number)