Spring在新的java对象中自动装配

时间:2016-01-05 09:19:31

标签: java spring spring-mvc spring-boot

我开始使用Spring Boot并得到一个关于如何在不受Springs应用程序上下文管理的java对象中自动装配Spring Beans的问题。

场景:在我的Spring Boot应用程序中,我想编写一个计划任务,首先获取类型为" environment"的主数据列表。来自数据库。对于每个环境" object将执行多个异步Rest调用,返回一些JSON数据(此处为" applicationServerData")。这些数据应保存在本地,直到所有其他呼叫响应到达。经过一些处理后,结果将被写入数据库。

所以我想到创建一种能够在本地保存所请求数据的处理器类。对于每个环境,将使用new运算符创建一个新对象:

@Slf4j
public class EnvironmentProcessingServiceImpl implements
    EnvironmentProcessingService {

@Autowired
private DataManagementFacade dataManagementFacade;

@Autowired
@Qualifier(value = "mock")
private ProductionDataClient productionDataClient;

private Environment environment;

private List<ApplicationServerDataHolder> applicationServerDataHolderList;

public EnvironmentProcessingServiceImpl(Environment environment) {
    this.environment = environment;
    this.applicationServerDataHolderList = new ArrayList<>();
}

现在的问题是,@Autowired不会起作用,因为对象不是由Spring管理的,但我不能简单地将其设为@service,因为如果我想保存数据我需要多个实例在同一个班。我读到了@Configurable注释的解决方案。这是好习惯吗?

或者我应该将类设为@service并创建另一个缓存所有数据的组件,并在任务完成后擦除以便下次运行时有空列表?

在这种情况下,您认为什么是良好做法。

4 个答案:

答案 0 :(得分:1)

Spring中的@service可以限定为Prototype,@ Scope(“prototype”),请点击此处:http://www.mkyong.com/spring/spring-bean-scopes-examples/

答案 1 :(得分:0)

你想根据不同的情况得到不同的实例,我认为你应该为一个接口提供更多的Impl,对吧?您可以使用Autowired接口,但是您应该决定要获取哪个实例,Spring无法做出选择,它只是帮助管理beans.eg,当type = 0时,您获得bean A;当type =时1,你得到豆B;在你使用@Autowired之前,你的spring应该已经存放了bean。你可以使用的另一种方式,另一种方法你可以使用。而bean的范围是Singlton default.Just my answer。

答案 2 :(得分:0)

我在没有Boot部分的情况下使用Spring。如果你能以某种方式获得上下文对象,你可以做的一个技巧就是调用:

context.getAutowireCapableBeanFactory().autowireBean(bean);

在我们的项目中,我们有一个手工制作的上下文查找机制,我们大多不需要传递它。我实际上试图避免使用autowire来支持在@Configuration类中注入事物并使它成为我处理Spring的唯一地方并且具有与Spring相关的导入。我们的球衣资源类是个例外。那些是由球衣而不是春天实例化的。我知道有一些精心设计的黑客可以修复并使两个框架相互配合。但我只是实现了一个静态方法,它返回静态单例上下文,如果它不存在则创建它。额外的好处是它大大减少了启动时发生的魔法量(春天很好,直到它不起作用,并没有告诉你原因)。

public class InbotSpringContextLoader {
    private static final Logger LOG = LoggerFactory.getLogger(InbotSpringContextLoader.class);
    private static AnnotationConfigApplicationContext context = null;

    private static final AtomicBoolean contextCreated = new AtomicBoolean(false);

    private static final Lock LOCK = new ReentrantLock();

    public static ApplicationContext context() {
        if(contextCreated.get()) {
            return context;
        } else {
            LOCK.lock();
            try {
                if(!contextCreated.get()) {
                    // init SLF4j JUL bridge
                    SLF4JBridgeHandler.removeHandlersForRootLogger();
                    SLF4JBridgeHandler.install();

                    context = new AnnotationConfigApplicationContext(RootConfig.class);

                    contextCreated.set(true);
                }
                return context;
            } finally {
                LOCK.unlock();
            }
        }
    }

    /**
     * Use this from jersey resources and other places where getting the context is kind of sucky
     * 
     * @param bean
     *            the bean where stuff needs to be injected
     */
    public static void autowire(Object bean) {
        InbotSpringContextLoader.context().getAutowireCapableBeanFactory().autowireBean(bean);
    }

    public static void destroy() {
        if(context != null) {
            context.close();
        }
    }
}

在我的资源构造函数中,我只是调用。

InbotSpringContextLoader.autowire(this);

答案 3 :(得分:0)

您可以从任何组件注入ApplicationContext:

@Autowired private ApplicationContext applicationContext;

然后你可以用它来获取一个bean:

Class<?> clazz = DemoBean.class;
DemoBean demoBean = (DemoBean)applicationContext.getAutowireCapableBeanFactory().autowire(clazz, AutowireCapableBeanFactory.AUTOWIRE_NO, false);

请注意,使用AUTOWIRE_NO时,任何使用@Autowired注释的成员变量仍将自动装配。