【发布时间】:2010-11-04 08:44:33
【问题描述】:
有没有办法将@Autowired 与静态字段一起使用。如果没有,还有其他方法可以做到这一点吗?
【问题讨论】:
有没有办法将@Autowired 与静态字段一起使用。如果没有,还有其他方法可以做到这一点吗?
【问题讨论】:
简而言之,没有。您不能在 Spring 中自动连接或手动连接静态字段。您必须编写自己的逻辑来执行此操作。
【讨论】:
@AutoWired 也有帮助
创建一个可以自动装配的 bean,它将初始化静态变量作为副作用。
【讨论】:
@Autowired 可以与 setter 一起使用,因此您可以让 setter 修改静态字段。
最后一个建议...不要
【讨论】:
@Component public class SpringAppEnv{ public static Environment _env; @Autowired public void setEnv(Environment env) {_env = env;} }
您可以使用 XML 表示法 和 MethodInvokingFactoryBean 来实现这一点。例如看here。
private static StaticBean staticBean;
public void setStaticBean(StaticBean staticBean) {
StaticBean.staticBean = staticBean;
}
您应该尽可能使用弹簧注射,因为这是推荐的方法,但这并不总是可行的,因为我相信您可以想象,并非所有东西都可以从弹簧容器中拉出或您可能会处理遗留系统。
使用这种方法进行笔记测试也可能更加困难。
【讨论】:
@Component("NewClass")
public class NewClass{
private static SomeThing someThing;
@Autowired
public void setSomeThing(SomeThing someThing){
NewClass.someThing = someThing;
}
}
【讨论】:
someThing 如果静态访问则已初始化:NewClass.staticMethodWhichUsesSomething(); 如果在应用程序初始化之前使用,可能会抛出 NPE
Instance methods should not write to "static" fields (squid:S2696)的警告吗?
在@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();
}
}
【讨论】:
Instance methods should not write to "static" fields (squid:S2696)的警告吗?
private static UserService userService = ApplicationContextHolder.getContext().getBean(UserService.class);
【讨论】:
你可以使用 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);
【讨论】:
免责声明这绝不是标准的,很可能有更好的弹簧方式来做到这一点。以上答案都没有解决连接公共静态字段的问题。
我想完成三件事。
我的对象看起来像这样
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 在调用函数时不会调用你的切面。让这变得更容易了,糟糕的是我在弄清楚之前就弄清楚了逻辑。
【讨论】:
想要添加自动连接静态字段(或常量)将被忽略,但也不会产生任何错误的答案:
@Autowired
private static String staticField = "staticValue";
【讨论】:
通常,通过对象实例设置静态字段是一种不好的做法。
为避免可选问题,您可以添加 synchronized 定义,并且仅在私有静态 Logger 记录器时设置它;
@Autowired
public synchronized void setLogger(Logger logger)
{
if (MyClass.logger == null)
{
MyClass.logger = logger;
}
}
:
【讨论】: