简体   繁体   English

Spring上下文作为运行时依赖

[英]Spring context as runtime dependency

I'm puzzled by this section of spring documentation. 我对春节文档的这一部分感到困惑。

For example, to create an application context and use dependency injection to configure an application, your Maven dependencies will look like this: 例如,要创建应用程序上下文并使用依赖项注入来配置应用程序,您的Maven依赖项将如下所示:

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

Note the scope can be declared as runtime if you don't need to compile against Spring APIs, which is typically the case for basic dependency injection use cases. 请注意,如果您不需要针对Spring API进行编译,则可以将范围声明为运行时,这通常是基本依赖项注入用例的情况。

I know about JSR 330 (DI annotations). 我知道JSR 330(DI注释)。 But how do you decouple from ApplicationContext class? 但是如何从ApplicationContext类中解耦? And if you do decouple from it why then still depend on spring? 如果你与它分离,为什么那么仍然依赖于春天?

How, for example, can quick start be rewritten having spring-context as a runtime dependency? 例如,如何将spring-context作为运行时依赖项重写快速启动 Or what would be the "basic dependency injection use case"? 或者什么是“基本依赖注入用例”?

I think the "basic use case" is referring to XML-based application contexts. 我认为“基本用例”指的是基于XML的应用程序上下文。 That documentation is saying if you aren't directly using Spring libraries in your code, then you won't have to include those libraries in your compilation classpath. 该文档说如果您没有在代码中直接使用Spring库,那么您将不必在编译类路径中包含这些库。 This is the case with XML configurations, as everything is Spring related is configured in XML, and therefore is not compiled. 这是XML配置的情况,因为Spring相关的所有内容都是用XML配置的,因此不会编译。

In the quick start you've linked, the author is using annotation-based application context configuration, which would require the Spring libraries to be included both at compile- and runtime. 在您快速启动时,作者正在使用基于注释的应用程序上下文配置,这需要在编译和运行时都包含Spring库。

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

there should only be a few key points where the application code needs to directly access the IoC container [...]. 应该只有几个关键点,应用程序代码需要直接访问IoC容器[...]。 If you're developing a web application, you may not need to directly access the IoC container at all since it will automatically handle instantiation of your controller and any beans it requires. 如果您正在开发Web应用程序,则可能根本不需要直接访问IoC容器,因为它将自动处理控制器及其所需的任何bean的实例化。

I'm not completely familiar with it, but it also looks like you can use JSR330 as you suggested with an XML configuration to autowire beans using annotations. 我并不完全熟悉它,但看起来你也可以使用JSR330建议使用XML配置来使用注释自动装配bean。 See here . 看到这里 This would allow using annotations, but without the need to include Spring in compile-time configurations. 这将允许使用注释,但不需要在编译时配置中包含Spring。

1 1

First of all, let's talk about DI. 首先,我们来谈谈DI。

Note from Spring Doc , 来自Spring Doc的注释,

Dependency management and dependency injection are different things. 依赖管理和依赖注入是不同的事情。

  • Dependency management is "assemble all the libraries needed (jar files) and get them onto your classpath at runtime, and possibly at compile time". 依赖管理是“组装所需的所有库(jar文件)并在运行时将它们放到类路径中,并且可能在编译时”。
  • Dependency injection is, suppose you want a Service object in your class, instead of create it using service = new Service(); 依赖注入是,假设您需要类中的Service对象,而不是使用service = new Service();创建它service = new Service(); , you let the spring framework handle the life cycle of that bean. ,让spring框架处理该bean的生命周期。

Example of Dependency management: 依赖管理示例:

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

So that you have all these jar files in your project. 这样您就可以在项目中拥有所有这些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

Example of Dependency Injection: 依赖注入示例:

In your quick-start example, you inject MessageService into MessagePrinter by using constructor injection. 快速 MessageService示例中,使用构造函数注入将MessageService注入到MessagePrinter You didn't create a MessageService anywhere. 您没有在任何地方创建MessageService Spring container creates it for you. 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 2

Now let's talk about transitive dependency and run-time dependency . 现在让我们谈谈传递依赖和运行时依赖

Transitive dependency 传递依赖

It means to discover the libraries that your own dependencies require and including them automatically. 它意味着发现您自己的依赖项所需的库并自动包含它们。
For example, if you specified dependencies A and B in pom.xml . 例如,如果您在pom.xml指定了依赖项A和B. And A depends on C, D. B depends on E. You don't need to include C, D, E in your configuration. A取决于C,D。B取决于E.您不需要在配置中包含C,D,E。 Because of transitive dependency, C, D, E will be included automatically. 由于传递依赖性,C,D,E将自动包含在内。

Runtime dependency 运行时依赖

It is one type of dependency scopes to limit the transitive dependency. 它是一种限制传递依赖的依赖范围。

"This scope indicates that the dependency is not required for compilation, but is for execution. It is in the runtime and test classpaths, but not the compile classpath." “这个范围表明编译不需要依赖,但是用于执行。它位于运行时和测试类路径中,但不是编译类路径。”

3 3

Now the question is: is there any case that for DI "you don't need to compile against Spring APIs", instead you can set the scope as runtime? 现在的问题是:对于DI“你不需要针对Spring API进行编译”,是否有任何情况,你可以将范围设置为运行时? Similar question here . 类似的问题在这里

Yes, one example I can think of is web application. 是的,我能想到的一个例子是Web应用程序。 Suppose I'm using Strtuts with Spring plugin. 假设我正在使用带有Spring插件的Strtuts。 (below example comes from "Struts 2 in Action" from Manning) (以下示例来自Manning的“Struts 2 in Action”)

I want to tell Spring to create an instance of the Login class to use as its action object for the request. 我想告诉Spring创建一个Login类的实例,以用作请求的操作对象。

add a spring web context listener to web.xml web.xml添加spring web上下文侦听器

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

define a bean Login named as springManagedLoginAction in applicationContext.xml applicationContext.xml定义一个名为springManagedLoginAction的bean Login

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

use this bean in the action class in struts-config-login.xml struts-config-login.xml的action类中使用这个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>

I am not sure I understood your question correctly, but it seems to me that why you are asking why do you need to have spring-context dependency if you are using JSR-330 annotations. 我不确定我是否正确理解了你的问题,但在我看来,为什么你要问为什么在使用JSR-330注释时你需要有弹簧上下文依赖。

Well, the answer from my point of view is you don't actually need the dependency on Spring if you are using only JSR-330 annotations but in order for them to work, you need some library which understands them and correctly builds the dependency graph for you and spring-context is one of such library. 好吧,从我的观点来看,如果你只使用JSR-330注释,你实际上并不需要对Spring的依赖,但为了使它们能够工作,你需要一些理解它们并正确构建依赖图的库。对于你和spring-context是这样的库之一。

The reason why it is a runtime dependency is because you can switch this provider at runtime, at least in theory. 它之所以是运行时依赖性,是因为您可以在运行时切换此提供程序,至少在理论上是这样。

You can implement your beans with a dependency on javax.inject (@Named, @Inject) in separate bundle. 您可以在单独的bundle中依赖javax.inject(@Named,@ Inject)来实现bean。 They will be usable from spring based project or any other container which has their own DI implementation. 它们可用于基于弹簧的项目或任何其他具有自己的DI实现的容器。

Here is sample of reworking spring based components to javax.inject (without splitting project to different bundles) http://www.mkyong.com/spring3/spring-3-and-jsr-330-inject-and-named-example/ 以下是javax.inject的基于rebble spring组件的示例(不将项目拆分为不同的bundle) http://www.mkyong.com/spring3/spring-3-and-jsr-330-inject-and-named-example/

If I understand correctly you are basically asking how the dependency injector is initialized and how you can inject the dependencies in your classes. 如果我理解正确,你基本上是在询问依赖注入器是如何初始化的,以及如何在类中注入依赖项。 In the quick start example you provided the application context is created manually in the main class. 在快速入门示例中,您提供的应用程序上下文是在主类中手动创建的。

ApplicationContext context = 
      new AnnotationConfigApplicationContext(Application.class);

According to the documentation 根据文件

Standalone application context, accepting annotated classes as input - in particular @Configuration-annotated classes, but also plain @Component types and JSR-330 compliant classes using javax.inject annotations. 独立的应用程序上下文,接受带注释的类作为输入 - 特别是@Configuration-annotated类,还有使用javax.inject注释的普通@Component类型和JSR-330兼容类。 Allows for registering classes one by one using register(Class...) as well as for classpath scanning using scan(String...) 允许使用寄存器(Class ...)逐个注册类,以及使用scan(String ...)进行类路径扫描

An alternative way to initialize spring is within your web.xml, where you use the ContextLoaderListner which will bootstrap the spring application context for you when the programs starts. 初始化spring的另一种方法是在web.xml中,您可以在其中使用ContextLoaderListner ,它将在程序启动时为您引导spring应用程序上下文。

The question about how to start spring in web.xml has already been answered here . 关于如何在web.xml中启动spring的问题已在这里得到解答。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM