我需要一些有关Spring的帮助(SpringBoot 1.3.2.RELEASE,Spring 4.3.11.RELEASE)。 用例很特殊,需要解释。
我有一个Spring应用程序,用于管理客户发送的请求。为了处理这些请求,我们需要使用带有@Autowired批注声明的服务。非常经典。
最近,我们决定处理来自其他国家/地区的新型请求。 关键是面对不同情况和不同类型的请求,我们决定实施策略模式。 ->根据请求的类型,我们执行在运行时选择的策略。每个策略都包含在一个具体的类中,并且所有策略共享一个相同的接口。
所以,我有:
现在我有:
问题在于,在加载Spring上下文之后,将无法再使用@Autowired注释。 我想在我的具体策略类中使用的所有服务都无法再通过@Autowired调用,并且保持为NULL。
我找到了一种解决方法,即将所需的服务作为参数传递给具体的策略类,但是我必须作为参数传递的服务数量因一种策略而异。
我认为我应该改为传递整个Spring上下文,但是我不知道该怎么做。而且我也不知道如何从上下文访问所有带注释的服务。
PS:我不显示代码行,因为我认为实际上没有必要。如果您认为使用代码更加明确,我会发送一些。
非常感谢。
答案 0 :(得分:0)
您应该声明一个工厂来映射依赖关系,而不是将服务声明为Bean,它将在将服务的具体实例返回到注入器之前检查请求。 在这里看看:
https://grokonez.com/spring-framework/spring-core/use-spring-factory-method-create-spring-bean
答案 1 :(得分:0)
您可以使用下面的类来静态获取应用程序上下文和Beans
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;
@Service
public class BeanUtil implements ApplicationContextAware {
private static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
}
public static <T> T getBean(Class<T> beanClass) {
return context.getBean(beanClass);
}
}
答案 2 :(得分:0)
大家很快回答我。 首先,对于您最近对所有评论的回答如此,我必须道歉。上一次冲刺的工作量很大,而新冲刺的效果并不好^^
我的需要是在Spring上下文完成创建和加载应用程序的所有部分之后,在对象上创建。
作为策略模式的一部分,我必须在运行时实例化一个类,具体取决于必须处理的请求文件中的某些值。此类需要使用@Autowired
批注声明的许多服务,但是所有自动装配的对象仍为'null
',因为在上下文加载后被调用。
这是我首先要使用的代码。 没有Spring没关系。
Function<Document, IStrategy> func = doc -> {
String strategyToApply = "";
IStrategy strategy = null;
switch(doc.getPlace()) {
case "Paris":
strategyToApply = "strategies_classes.ProcessParis";
break;
case "New York":
strategyToApply = "strategies_classes.ProcessNewYork";
break;
}
case "Roma":
...
try {
**Class<?> classToUse = Class.forName(strategyToApply);
strategy = (IStrategy) classToUse.newInstance();**
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return strategy;
};
Consumer<Document> consumerStrategy = doc -> {
IStrategy strategy = func.apply(doc);
strategy.bookRequest(doc);
};
documents.stream()
.forEach(consumerStrategy);
我终于找到了魔法对象。当Spring对象的生命周期不符合我们自己的概念时,这是一个很好的解决方法。
要使用它,只需使用@Autowired进行声明:
@Autowired
private AutowireCapableBeanFactory autowireBeanFactory;
请注意,AutowireCapableBeanFactory是一个Spring对象,您无需在其他任何地方声明!!
然后,使用起来非常简单(我设计了一种全新的服务,与您在上面看到的完全不同,但是它的作用相同):
public <T> T getStrategyToUse(Entity bookingCtr, Funder funder, StrategyEnum strategy) throws FunctionalException {
String strategyToApply = null;
strategyToApply = strategyDao.getClassToApply(bookingCtr, funder, strategy);
Class<?> classToUse;
try {
classToUse = Class.forName(strategyToApply);
T strat = (T) **autowireBeanFactory.getBean**(classToUse);
return (T) strat;
} catch (ClassNotFoundException e) {
LOGGER.error("The indicated Strategy class was not found", e);
}
return null;
}
在运行时加载时,将立即实例化所选的类,并且其所有自动装配对象将不再为空。
我希望这会有所帮助。