Spring上下文作为运行时依赖

时间:2016-02-25 14:13:18

标签: java spring

我对this section的春季文档感到困惑。

  

例如,要创建应用程序上下文并使用依赖项注入来配置应用程序,Maven依赖项将如下所示:

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.2.5.RELEASE</version>
        <scope>runtime</scope>
    </dependency> 
</dependencies>
     

注意,如果不需要针对Spring API进行编译,则可以将作用域声明为运行时,这通常是基本依赖项注入用例的情况。

我了解JSR 330(DI注释)。但是你如何与ApplicationContext课程脱钩?如果你从中解耦,为什么还要依赖弹簧?

例如,如果spring-context作为运行时依赖项,可以重写quick start吗?或者什么是&#34;基本依赖注入用例&#34;?

5 个答案:

答案 0 :(得分:5)

我认为&#34;基本用例&#34;指的是基于XML的应用程序上下文。该文档说如果您不在代码中直接使用Spring库,那么您不必在编译类路径中包含这些库。这是XML配置的情况,因为Spring相关的所有内容都是用XML配置的,因此不会编译。

在您快速启动时,作者正在使用基于注释的应用程序上下文配置,这需要在编译和运行时都包含Spring库。

示例XML配置: http://www.springbyexample.org/examples/intro-to-ioc-creating-a-spring-application.html

  

应该只有几个关键点,应用程序代码需要直接访问IoC容器[...]。如果您正在开发Web应用程序,则可能根本不需要直接访问IoC容器,因为它将自动处理控制器及其所需的任何bean的实例化。

我并不完全熟悉它,但您也可以使用JSR330建议使用XML配置来使用注释自动装配bean。 见here。这将允许使用注释,但不需要在编译时配置中包含Spring。

答案 1 :(得分:3)

<强> 1

首先,让我们谈谈DI。

来自Spring Doc的注释,

  

依赖管理和依赖注入是不同的事情。

  • 依赖管理是#34;汇集所需的所有库(jar文件)并在运行时将它们放到类路径中,并且可能在编译时#34;
  • 依赖注入是,假设您想在类中使用Service对象,而不是使用service = new Service();创建它,则让spring框架处理该bean的生命周期。

依赖关系管理示例:

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.2.5.RELEASE</version>
    </dependency> 
</dependencies>

这样你就可以在项目中拥有所有这些jar文件。

spring-context-4.2.5.RELEASE.jar
spring-aop-4.2.5.RELEASE.jar
spring-beans-4.2.5.RELEASE.jar
spring-core-4.2.5.RELEASE.jar

依赖注入示例:

quick-start示例中,您使用构造函数注入将MessageService注入MessagePrinter。你没有在任何地方创建MessageService。 Spring容器为您创建它。

@Component
public class MessagePrinter {
    final private MessageService service;
    @Autowired
    public MessagePrinter(MessageService service) {
        this.service = service;
    }
    public void printMessage() {
        System.out.println(this.service.getMessage());
    }
}

@Configuration
@ComponentScan
public class Application {
    @Bean
    MessageService mockMessageService() {
        return new MessageService() {
            public String getMessage() {
              return "Hello World!";
            }
        };
    }
    ...
}

<强> 2

现在让我们谈谈transitive dependency and run-time dependency

传递依赖

这意味着要发现您自己的依赖项所需的库并自动包含它们。
例如,如果您在pom.xml中指定了依赖关系A和B. A取决于C,D。B取决于E.您不需要在配置中包含C,D,E。 由于传递依赖性,C,D,E将自动包含在内。

运行时依赖

这是一种限制传递依赖的依赖范围。

  

&#34;此范围表示不需要依赖关系   编译,但是用于执行。它在运行时和测试中   classpaths,但不是编译类路径。&#34;

第3

现在的问题是:对于DI&#34;有什么情况你不需要针对Spring API&#34;进行编译,而是可以将范围设置为运行时?类似问题here

是的,我能想到的一个例子是Web应用程序。假设我使用带有Spring插件的Strtuts。 (以下示例来自&#34; Struts 2 in Action&#34;来自Manning)

我想告诉Spring创建一个Login类的实例,以用作请求的操作对象。

web.xml

添加spring web上下文侦听器
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

定义一个名为Login的bean springManagedLoginAction applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
    <bean id="portfolioService" class="manning.chapterNine.utils.PortfolioServiceJPAImpl"/>
    <bean id="springManagedLoginAction" class="manning.chapterNine.Login" scope="prototype">
        <property name="portfolioService" ref="portfolioService"/>
    </bean>
</beans>

struts-config-login.xml

的操作类中使用此bean
<action name="Login" class="springManagedLoginAction">
    <result type="redirectAction">
        <param name="actionName">AdminPortfolio</param>
        <param name="namespace">/chapterEight/secure</param>
    </result>
    <result name="input">/chapterEight/Login.jsp</result>
</action>

答案 2 :(得分:0)

我不确定我是否正确理解了您的问题,但在我看来,为什么您要问为什么在使用JSR-330注释时需要具有Spring-context依赖性。

嗯,从我的观点来看,如果你只使用JSR-330注释,你实际上并不需要对Spring的依赖,但是为了让它们工作,你需要一些理解它们并正确构建的库你和spring-context的依赖图就是这样一个库。

它之所以是运行时依赖性,是因为您可以在运行时切换此提供程序,至少在理论上是这样。

答案 3 :(得分:-1)

您可以在单独的bundle中依赖javax.inject(@Named,@ Inject)来实现bean。它们可用于基于弹簧的项目或任何其他具有自己的DI实现的容器。

以下是javax.inject的基于reworking spring的组件示例(不将项目拆分为不同的bundle) http://www.mkyong.com/spring3/spring-3-and-jsr-330-inject-and-named-example/

答案 4 :(得分:-1)

如果我理解正确,您基本上会询问如何初始化依赖注入器以及如何在类中注入依赖项。在快速入门示例中,您提供的应用程序上下文是在主类中手动创建的。

ApplicationContext context = 
      new AnnotationConfigApplicationContext(Application.class);

根据documentation

  

独立应用程序上下文,接受带注释的类作为输入 -   特别是@Configuration-annotated类,但也很简单   使用javax.inject的@Component类型和JSR-330兼容类   注释。允许使用逐个注册类   注册(Class ...)以及使用的类路径扫描   扫描(字符串...)

初始化spring的另一种方法是在你的web.xml中,你可以使用ContextLoaderListner在程序启动时为你引导spring应用程序上下文。

关于如何在web.xml中启动spring的问题已经回答here