您可以将 @Autowired 与静态字段一起使用吗?

发布于 2024-07-24 23:03:21 字数 57 浏览 6 评论 0原文

有没有办法将 @Autowired 与静态字段一起使用。 如果没有,还有其他方法可以做到这一点吗?

Is there some way to use @Autowired with static fields. If not, are there some other ways to do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

君勿笑 2024-07-31 23:03:22

创建一个可以自动装配的 bean,它会初始化静态变量作为副作用。

Create a bean which you can autowire which will initialize the static variable as a side effect.

匿名。 2024-07-31 23:03:22

想要添加自动接线静态字段(或常量)将被忽略的答案,但也不会产生任何错误:

@Autowired
private static String staticField = "staticValue";

Wanted to add to answers that auto wiring static field (or constant) will be ignored, but also won't create any error:

@Autowired
private static String staticField = "staticValue";
街道布景 2024-07-31 23:03:22

您可以使用XML 表示法MethodInvokingFactoryBean 来实现此目的。 例如,请查看 这里

private static StaticBean staticBean;

public void setStaticBean(StaticBean staticBean) {
   StaticBean.staticBean = staticBean;
}

您应该尽可能使用 spring 注入,因为这是推荐的方法,但这并不总是可能的,因为我确信您可以想象,因为并非所有内容都可以从 spring 容器中提取,或者您可能会处理与遗留系统。

请注意,使用这种方法进行测试也可能会更加困难。

You can achieve this using XML notation and the MethodInvokingFactoryBean. For an example look here.

private static StaticBean staticBean;

public void setStaticBean(StaticBean staticBean) {
   StaticBean.staticBean = staticBean;
}

You should aim to use spring injection where possible as this is the recommended approach but this is not always possible as I'm sure you can imagine as not everything can be pulled from the spring container or you maybe dealing with legacy systems.

Note testing can also be more difficult with this approach.

披肩女神 2024-07-31 23:03:22

你可以使用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);

You can use ApplicationContextAware

@Component
public class AppContext implements ApplicationContextAware{
    public static ApplicationContext applicationContext;

    public AppBeans(){
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

then

static ABean bean = AppContext.applicationContext.getBean("aBean",ABean.class);
始终不够爱げ你 2024-07-31 23:03:22

免责声明 这绝不是标准的,很可能有更好的 Spring 方法来做到这一点。 上述答案都没有解决公共静态场的接线问题。

我想完成三件事。

  1. 使用 spring 来“自动装配”(我使用 @Value)
  2. 公开一个公共静态值
  3. 防止修改

我的对象看起来像这样

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 在调用函数时不会调用您的方面。 让这变得更容易,糟糕的是我在弄清楚之前已经弄清楚了逻辑。

Disclaimer This is by no means standard and there could very well be a better spring way of doing this. None of the above answers address the issues of wiring a public static field.

I wanted to accomplish three things.

  1. Use spring to "Autowire" (Im using @Value)
  2. Expose a public static value
  3. Prevent modification

My object looks like this

private static String BRANCH = "testBranch";

@Value("${content.client.branch}")
public void finalSetBranch(String branch) {
    BRANCH = branch;
}

public static String BRANCH() {
    return BRANCH;
}

We have checked off 1 & 2 already now how do we prevent calls to the setter, since we cannot hide it.

@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;
    }
}

This aspect will wrap all methods beginning with final and throw an error if they are called.

I dont think this is particularly useful, but if you are ocd and like to keep you peas and carrots separated this is one way to do it safely.

Important Spring does not call your aspects when it calls a function. Made this easier, to bad I worked out the logic before figuring that out.

怂人 2024-07-31 23:03:22

一般来说,通过对象实例设置静态字段是一种不好的做法。

为了避免可选问题,您可以添加 synchronized 定义,并仅在 private static Logger logger; 时设置它;

@Autowired
public synchronized void setLogger(Logger logger)
{
    if (MyClass.logger == null)
    {
        MyClass.logger = logger;
    }
}

:

Generally, setting static field by object instance is a bad practice.

to avoid optional issues you can add synchronized definition, and set it only if private static Logger logger;

@Autowired
public synchronized void setLogger(Logger logger)
{
    if (MyClass.logger == null)
    {
        MyClass.logger = logger;
    }
}

:

溺孤伤于心 2024-07-31 23:03:22

解决方案 1:使用构造函数 @Autowired 对于静态字段

@Component
public class MyClass {

    private static MyService service;

    @Autowired
    public MyClass(MyService service) {
        TestClass.service= service;
    }
}

解决方案 2:使用 @PostConstruct 将值设置为静态字段

@Component
public class MyClass {

    private static MyService service;

    @Autowired
    private MyService srv;

    @PostConstruct
    public void init() {
        this.service= srv;
    }
}

请参阅此处了解更多详细信息

Solution 1 : Using Constructor @Autowired For Static Field

@Component
public class MyClass {

    private static MyService service;

    @Autowired
    public MyClass(MyService service) {
        TestClass.service= service;
    }
}

Solution 2 : Using @PostConstruct to set the value to Static Field

@Component
public class MyClass {

    private static MyService service;

    @Autowired
    private MyService srv;

    @PostConstruct
    public void init() {
        this.service= srv;
    }
}

Refer here for more detail

难得心□动 2024-07-31 23:03:22

我使用私有静态内部组件:FieldSetter,注入静态字段:MyBean,最后SelfDestroyBean将帮助我删除多余的FiledSetter< /strong> 豆

public final class MyClass {
    private static MyBean myBean;

    @Component
    private static class FieldSetter extends SelfDestroyBean {
          public FieldSetter(MyBean myBean) {
              MyClass.myBean = myBean;
          }
    }
}
    
@SuppressWarnings("SpringJavaAutowiredMembersInspection")
public abstract class SelfDestroyBean {
    @Autowired
    private ApplicationContext context;

    @PostConstruct
    public void destroy() {
        final String[] beanNames = context.getBeanNamesForType(this.getClass());

        final BeanDefinitionRegistry registry =
                ((BeanDefinitionRegistry) context.getAutowireCapableBeanFactory());
        for (String beanName : beanNames) {
            registry.removeBeanDefinition(beanName);
        }
    }
}

I use private static inner Component: FieldSetter, to inject static field: MyBean, at last SelfDestroyBean will help me remove redundant FiledSetter bean

public final class MyClass {
    private static MyBean myBean;

    @Component
    private static class FieldSetter extends SelfDestroyBean {
          public FieldSetter(MyBean myBean) {
              MyClass.myBean = myBean;
          }
    }
}
    
@SuppressWarnings("SpringJavaAutowiredMembersInspection")
public abstract class SelfDestroyBean {
    @Autowired
    private ApplicationContext context;

    @PostConstruct
    public void destroy() {
        final String[] beanNames = context.getBeanNamesForType(this.getClass());

        final BeanDefinitionRegistry registry =
                ((BeanDefinitionRegistry) context.getAutowireCapableBeanFactory());
        for (String beanName : beanNames) {
            registry.removeBeanDefinition(beanName);
        }
    }
}
我只土不豪 2024-07-31 23:03:22
private static UserService userService = ApplicationContextHolder.getContext().getBean(UserService.class);
private static UserService userService = ApplicationContextHolder.getContext().getBean(UserService.class);
许一世地老天荒 2024-07-31 23:03:21

简而言之,不。 您无法在 Spring 中自动装配或手动装配静态字段。 您必须编写自己的逻辑才能做到这一点。

In short, no. You cannot autowire or manually wire static fields in Spring. You'll have to write your own logic to do this.

给不了的爱 2024-07-31 23:03:21
@Component("NewClass")
public class NewClass{
    private static SomeThing someThing;

    @Autowired
    public void setSomeThing(SomeThing someThing){
        NewClass.someThing = someThing;
    }
}
@Component("NewClass")
public class NewClass{
    private static SomeThing someThing;

    @Autowired
    public void setSomeThing(SomeThing someThing){
        NewClass.someThing = someThing;
    }
}
噩梦成真你也成魔 2024-07-31 23:03:21

@Autowired 可以与 setter 一起使用,这样您就可以让 setter 修改静态字段。

最后一个建议...不要

@Autowired can be used with setters so you could have a setter modifying an static field.

Just one final suggestion... DON'T

鸠魁 2024-07-31 23:03:21

在 @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();
   }
}

Init your autowired component in @PostConstruct method

@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();
   }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文