- 在application.properties中设置值
efs.url=http://efs-beta.test.com
- 在服务中注入价值
@Data
@Named
public class DimensionService implements IDimensionService {
@Value("${efs.url}")
public String efsUrl;
}
- 运行测试
public class IDimensionServiceTest{
@Inject
private DimensionService dimensionService;
@Test
public void test() {
System.out.println(dimensionService.getEfsUrl() + "t" + dimensionService.efsUrl);
}
}
- 控制台打印
http://efs-beta.test.com null
为什么不能直接通过@Value获取公共字段?
dimensionService.getClass()
返回xxx.DimensionService$$EnhancerBySpringCGLIB$$eda602b7
这是DimensionService
的运行时生成的子类,很可能是SpringAOP代理。Spring AOP允许面向方面编程(AOP(,这是一种实现横切关注点的方法,这些关注点需要在程序中的许多其他无关方法中以相同的方式完成。
例如,Spring就是这样实现它的@Transactional
的,它将用于启动、提交和回滚事务的代码添加到所有带有此注释的方法(或以其他方式配置为事务的方法(。这也是Spring实现@Timed
的方式,用于收集运行时度量以及许多其他内容。
也就是说,SpringAOP允许将额外的代码附加到满足某些标准的bean方法。为了附加这些附加代码,SpringAOP使用了一个代理对象。例如,如果你有
class X {
@Inject
Y y;
}
class Y {
public void foo() {
// do something
}
}
Spring AOP将在运行时生成一个额外的类,如下所示:
class Y$$EnhancedBySpringCGLIB$$eda602b7 extends Y {
Y target;
@Override
public void foo() {
// do things before
var result = target.foo();
// do things after
return result;
}
}
并将该类的实例注入到请求CCD_ 8的每个人中。也就是说,在运行时,我们有以下对象:
+-------+
| X |
+-------+
|
|
v
+------------------+
| Y$$EnhancerBy... |
+------------------+
|
|
v
+-----+
| Y |
+-----+
这个代理对象尽可能模仿真实对象的行为(添加了功能(。特别是,所有公共方法都被重写以委托给真实对象。然而,Java不允许重写字段访问,因此Spring AOP无法将字段访问重定向到真实对象,并且代理的(空(字段将被读取,从而打破了这种错觉。除了编写编译器插件,并要求所有可能访问这些字段的代码都由该插件编译之外,Spring AOP无法解决这一问题。
这意味着,无论何时访问Springbean,都应该通过其公共方法进行访问(在从Spring-this
获得的引用上,它指向的是真实对象,而不是代理,并且没有额外的功能(。
关于Spring AOP的更多信息可以在Spring参考手册中找到,特别是在Spring的面向方面编程和理解AOP代理中。
如果您正在运行测试,请检查您是否也在测试包中设置了参数建议使用yml文件进行配置参观https://www.baeldung.com/spring-value-annotation