Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 静态字段@Autowire的替代方案_Java_Spring_Autowired - Fatal编程技术网

Java 静态字段@Autowire的替代方案

Java 静态字段@Autowire的替代方案,java,spring,autowired,Java,Spring,Autowired,对于静态字段,@Autowire有哪些替代方案 我问了很多问题,明白了为什么@Autowired不能与静态字段一起使用。问题的公认答案提到 要做到这一点,您必须编写自己的逻辑,因为@Autowired无法做到这一点 被使用 由于我是依赖注入的新手,我不知道要编写我们自己的逻辑来实现这一点需要遵循哪些步骤 我得到的是,new不能用于创建对象,因为它会将这两个类紧密地耦合在一起,而DI是它的解决方案。同样,在同一问题的第二个答案中,不建议对setters使用@autowired。那么,在不使用@Au

对于静态字段,
@Autowire
有哪些替代方案

我问了很多问题,明白了为什么
@Autowired
不能与静态字段一起使用。问题的公认答案提到

要做到这一点,您必须编写自己的逻辑,因为@Autowired无法做到这一点 被使用

由于我是依赖注入的新手,我不知道要编写我们自己的逻辑来实现这一点需要遵循哪些步骤


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

您可以创建一个bean,在每次刷新上下文(即完成)时触发一个方法。在该方法中,您将设置您喜欢的任何静态字段,例如,这将向彼此注入两个bean,即使它们是静态的

import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;

public class ApplicationListenerBean implements ApplicationListener {

    @Autowired
    SomeBean one;

    @Autowired
    SomeOtherBeab two;

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        if (event instanceof ContextRefreshedEvent) {
            one.setTwo(two);
            two.setOne(one);
        }
    }
}
有一个“解决办法”:不要这样做。在没有看到您的代码示例的情况下,我会说,如果依赖于动态(注入)的东西,为什么要创建“静态”的东西

通常我会重新考虑责任。将可能的静态部分重新定位到静态util类。对于需要注射的零件,创建一个正常的维修


(是的,总会有变通办法,但当你需要变通办法时,你通常应该考虑更好的解决方案)。

我会给你两个选择。第一个当前处于生产环境中。第二种选择是我在再次思考这个问题后提出的

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

备选案文1 实现ApplicationContextAware
我遇到了一个情况,我们需要自动连接一个静态场。我正在使用遗留代码,我们希望在新代码中使用spring和jpa(hibernate)。一般来说,自动连接静态字段是一种不好的做法,但我相信,在考虑应用程序的更大好处时,可以激发这种做法

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

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

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

<bean id="dbHandler" class="se.ucr.db.DbHandler" depends-on="dataSource"/>
一个简单的Singleton将注入上面定义的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();
    }

}
最后是spring上下文:

<?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>

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

必须指定
factory method=“getInstance”
,否则将失败


我希望这对某些人有用。

我需要在一个日志类中集成现有类的功能(模糊处理),该类具有所有静态方法。这个日志类的静态方法在1000多个地方使用。所以我实现这一点的唯一方法是创建一个模糊类的实例,并将引用分配给静态变量,然后引用静态变量。成功了

private static LogObfuscator staticObfuscator;

@Resource(name = "domain.logging.Obfuscator")
private  LogObfuscator obfuscatorInstance;

@PostConstruct
public void init() {
    staticObfuscator= obfuscatorInstance;
}

如其他答案中所述,您可以将autowire置于非静态方法上,并修改其中所需的静态字段。这比创建自定义注释更简单。链接:但这与使用@autowired with setters是一样的,在我链接的同一个问题的第二个答案中不建议使用@autowired,同样在你给出的链接中提到了“尽可能避免使用这种技术”,没有其他可接受的解决方案吗?顺便说一句,DI的部分好处是你不需要静态字段。spring不会因为支持这种类型的东西而自暴自弃,因为使用spring(您可以声明性地指定作用域)应该可以消除实施这种反模式的需要。
private static LogObfuscator staticObfuscator;

@Resource(name = "domain.logging.Obfuscator")
private  LogObfuscator obfuscatorInstance;

@PostConstruct
public void init() {
    staticObfuscator= obfuscatorInstance;
}