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