用于静态字段的 @Autowire 的替代方案

Anu*_*bha 3 java spring autowired

@Autowire静态字段的替代方法是什么?

我经历了很多问题并理解为什么@Autowired不能与静态字段一起使用。这个问题的公认答案提到

您必须编写自己的逻辑来执行此操作,因为不能使用 @Autowired。

由于我是依赖注入的新手,我不知道编写我们自己的逻辑来执行此操作必须遵循哪些步骤。

我得到的是它new不能用于创建对象,因为它会将 2 个类紧密耦合,而 DI 旨在成为它的解决方案。@autowired在同一问题的第二个答案中也不建议使用setter。那么在不使用的情况下实现相同效果的替代方法是@Autowire什么?

ema*_*ren 5

我会给你两个选择。第一个目前在生产环境中。第二种选择是我再次思考这个问题后想到的。

尽管如此,这应该避免,但如果您的代码目前不了解 Spring,则可以使用它。

备选方案 1

实现 ApplicationContextAware
我遇到过需要自动装配静态字段的情况。我正在处理遗留代码,我们希望在新代码中使用 spring 和 jpa(休眠)。一般来说,自动装配静态字段是不好的做法,但我相信在考虑对应用程序更大的好处时可以激发它。

我们通过实现 ApplicationContextAware 解决了这种情况。吹:

public class DbHandler implements ApplicationContextAware {

private static DataSource dataSource;

protected DbHandler(){
    //Needs to be protected (not private) for Spring
}

//This method is used in many places in the code, and we can not change how it is 
//used. We wanted to use a datasource from Spring
public static Connection getConnection() throws java.sql.SQLException {
    return dataSource.getConnection();

}

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    DbHandler.dataSource = applicationContext.getBean("dataSource", javax.sql.DataSource.class);
}
Run Code Online (Sandbox Code Playgroud)

}

由于该类不在 spring 扫描的包中,我们将其添加到 context.xml

<bean id="dbHandler" class="se.ucr.db.DbHandler" depends-on="dataSource"/>
Run Code Online (Sandbox Code Playgroud)

这不像编写@Autowired 那样容易,但它确实有效。

备选方案 2

创建单例

一个可以注入的bean:

@Component
public class BeanToInject {

    private static final Logger LOGGER = LoggerFactory.getLogger(BeanToInject.class);

    public String getValue() {
        return "Value from SpringBean";
    }
}
Run Code Online (Sandbox Code Playgroud)

一个简单的 Singelton 将注入上面定义的 bean:

public class NeedStaticFieldInjected {

    private static final Logger LOGGER = LoggerFactory.getLogger(NeedStaticFieldInjected.class);

    private static NeedStaticFieldInjected INSTANCE;

    private NeedStaticFieldInjected() {
        //private constructor
    }

    @Autowired
    private BeanToInject beanToInject;

    public static NeedStaticFieldInjected getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new NeedStaticFieldInjected();
        }
        return INSTANCE;
    }


    public static String getValueFromSpringBean() {
        if (INSTANCE.beanToInject  == null)
            return "Not initialized correctly";

        return INSTANCE.beanToInject.getValue();
    }

}
Run Code Online (Sandbox Code Playgroud)

最后,弹簧上下文:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:context="http://www.springframework.org/schema/context"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

<context:component-scan base-package="org.emancipering.components"/>


<bean id="needStaticFieldInjected" class="org.emancipering.components.NeedStaticFieldInjected" factory-method="getInstance" />

</beans>
Run Code Online (Sandbox Code Playgroud)

您将通过静态变量访问自动装配的属性INSTANCE,如 中所示NeedStaticFieldInjected .getValueFromSpringBean()。这非常接近注入静态场的目的。当然,可以有更多的 Autowired 属性,但我只是在这个例子中添加了一个。

重要的factory-method="getInstance"是指定,否则这将失败。

我希望这对某人有用。