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:
<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.
I know about JSR 330 (DI annotations). But how do you decouple from ApplicationContext
class? 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? Or what would be the "basic dependency injection use case"?
I think the "basic use case" is referring to XML-based application contexts. 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. This is the case with XML configurations, as everything is Spring related is configured in XML, and therefore is not compiled.
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.
Sample XML configuration: 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 [...]. 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.
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. See here. This would allow using annotations, but without the need to include Spring in compile-time configurations.
1
First of all, let's talk about DI.
Note from Spring Doc,
Dependency management and dependency injection are different things.
Service
object in your class, instead of create it using service = new Service();
, you let the spring framework handle the life cycle of that 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.
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. You didn't create a MessageService
anywhere. Spring container creates it for you.
@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
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
. And A depends on C, D. B depends on E. You don't need to include C, D, E in your configuration.
Because of transitive dependency, C, D, E will be included automatically.
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
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? Similar question here.
Yes, one example I can think of is web application. Suppose I'm using Strtuts with Spring plugin. (below example comes from "Struts 2 in Action" from Manning)
I want to tell Spring to create an instance of the Login
class to use as its action object for the request.
add a spring web context listener to web.xml
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
define a bean Login
named as springManagedLoginAction
in
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>
use this bean in the action class in struts-config-login.xml
<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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With