有什么方法可以@Autowired
与静态字段一起使用。如果没有,还有其他方法可以做到这一点吗?
11 回答
简而言之,没有。您不能在 Spring 中自动连接或手动连接静态字段。您必须编写自己的逻辑来执行此操作。
@Component("NewClass")
public class NewClass{
private static SomeThing someThing;
@Autowired
public void setSomeThing(SomeThing someThing){
NewClass.someThing = someThing;
}
}
@Autowired
可以与 setter 一起使用,因此您可以让 setter 修改静态字段。
只有一个最后的建议......不要
在 @PostConstruct 方法中初始化您的自动装配组件
@Component
public class TestClass {
private static AutowiredTypeComponent component;
@Autowired
private AutowiredTypeComponent autowiredComponent;
@PostConstruct
private void init() {
component = this.autowiredComponent;
}
public static void testMethod() {
component.callTestMethod();
}
}
创建一个可以自动装配的 bean,它将初始化静态变量作为副作用。
想要添加自动连接静态字段(或常量)将被忽略的答案,但也不会产生任何错误:
@Autowired
private static String staticField = "staticValue";
您可以使用XML 表示法和MethodInvokingFactoryBean
. 例如看这里。
private static StaticBean staticBean;
public void setStaticBean(StaticBean staticBean) {
StaticBean.staticBean = staticBean;
}
您应该尽可能使用弹簧注入,因为这是推荐的方法,但这并不总是可行的,因为我相信您可以想象并非所有东西都可以从弹簧容器中提取出来,或者您可能会处理遗留系统。
使用这种方法进行笔记测试也可能更加困难。
您可以使用 ApplicationContextAware
@Component
public class AppContext implements ApplicationContextAware{
public static ApplicationContext applicationContext;
public AppBeans(){
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
然后
static ABean bean = AppContext.applicationContext.getBean("aBean",ABean.class);
免责声明这绝不是标准的,很可能有更好的弹簧方式来做到这一点。以上答案都没有解决连接公共静态字段的问题。
我想完成三件事。
- 使用弹簧“自动装配”(我使用@Value)
- 公开一个公共静态值
- 防止修改
我的对象看起来像这样
private static String BRANCH = "testBranch";
@Value("${content.client.branch}")
public void finalSetBranch(String branch) {
BRANCH = branch;
}
public static String BRANCH() {
return BRANCH;
}
我们已经检查了 1 和 2 现在我们如何防止调用 setter,因为我们无法隐藏它。
@Component
@Aspect
public class FinalAutowiredHelper {
@Before("finalMethods()")
public void beforeFinal(JoinPoint joinPoint) {
throw new FinalAutowiredHelper().new ModifySudoFinalError("");
}
@Pointcut("execution(* com.free.content.client..*.finalSetBranch(..))")
public void finalMethods() {}
public class ModifySudoFinalError extends Error {
private String msg;
public ModifySudoFinalError(String msg) {
this.msg = msg;
}
@Override
public String getMessage() {
return "Attempted modification of a final property: " + msg;
}
}
这个方面将包装所有以 final 开头的方法,如果它们被调用则抛出错误。
我不认为这特别有用,但如果你是强迫症并且喜欢把豌豆和胡萝卜分开,这是一种安全的方法。
重要Spring 在调用函数时不会调用你的切面。让这更容易,糟糕的是,我在弄清楚之前制定了逻辑。
通常,通过对象实例设置静态字段是一种不好的做法。
为避免可选问题,您可以添加synchronized
定义,并仅在私有静态 Logger 记录器时设置它;
@Autowired
public synchronized void setLogger(Logger logger)
{
if (MyClass.logger == null)
{
MyClass.logger = logger;
}
}
:
private static UserService userService = ApplicationContextHolder.getContext().getBean(UserService.class);