Spring Dependency Injection and Inversion of Control Container Concepts: Difference between revisions

From NovaOrdis Knowledge Base
Jump to navigation Jump to search
Line 42: Line 42:


The equivalent of the XML bean definition file is a Java class annotated with @Configuration.
The equivalent of the XML bean definition file is a Java class annotated with @Configuration.
The @Configuration annotation indicates that the class it annotates is a configuration class that will provide [[#Spring_Components|beans]] to the Spring [[#Application_Context|application context]]. The class must expose one or more methods annotated with [[@Bean]]. The Spring container will invoke those methods to obtain the bean definitions.
The @Configuration annotation indicates that the class it annotates is a configuration class that will provide [[#Spring_Components|beans]] to the Spring [[#Application_Context|application context]]. The class must expose one or more methods annotated with [[@Bean]]. A @Bean-annotated method is the equivalent of an <bean> element in an Spring XML configuration file. The Spring container will invoke those methods to obtain the bean definitions.


For Java-based configuration, [[@Configuration]]/[[@Bean]]. <font color=red><span id='RETURN_HERE'></span>RETURN_HERE</font>.
For Java-based configuration, [[@Configuration]]/[[@Bean]]. <font color=red><span id='RETURN_HERE'></span>RETURN_HERE</font>.

Revision as of 20:52, 4 November 2018

External

  • www.tutorialspoint.com/spring/index.htm

Internal

Overview

Spring is a dependency injection framework. Its main responsibilities are to provide a configuration model that specifies how components should be defined and what are the dependencies between defined components, detect conforming components in the libraries available on the classpath, instantiate the component graph while transitively honoring the dependency relationships - by instantiating the dependency before the dependent and injecting the appropriate dependency references into dependents - and finally expose the components to the application. Instantiation, dependency injection and component life cycle management take place within the Spring IoC container. Support for different application architectures, including messaging, transactions and persistence is built in top of the core container.

Dependency Injection

Rather than have individual components create and manage the lifecycle of their dependency components, a dependency-injected application relies on container to first create all components, then to inject them into other components that need them. Injection is typically done through constructor arguments or property setters.

Configuration Model

This section refers to component configuration. Configuration as in external data that is provided to the application in form of properties or environment variables, and which potentially modifies the behavior of the application, is addressed in the "Application Configuration Concepts" section.

Spring runtime expects to receive information about what components it should create and how those components should be wired together either in form of XML files or, since Spring 2.5, as annotation-based metadata embedded within the bytecode of the component classes themselves and referred to as Java-based configuration. This information that tells Spring how to build its components and what other components they depend on is called configuration metadata. Configuration metadata expressed as XML is equivalent with configuration metadata provided in form of Java annotations. Either can be used to the same effect.

XML-based configuration and Java-based configuration can also be combined and used together. However, when they are used together, annotation injection is performed before XML injection, thus the XML configuration overrides the annotations for properties wired through both approaches.

Configuration metadata includes the definitions of what constitutes a component - the Java fully qualified classname of the component class, the component's dependencies on other components, the component lifecycle details and where to find component classes. Depending on the metadata format, this information is provided in different formats. For example, in case of XML-based configuration, the fully qualified class name is provided in the "class" attribute of the <bean> element. However, for Java-based configuration, a component class is annotated as a @Component or a similar annotation, so Spring runtime has already the class information when it detects the annotation in the class' bytecode.

XML-based Configuration Metadata

The XML-based configuration historically precedes Java-based configuration. First Spring releases came with only XML configuration support.

This is an example of a simple Spring XML configuration file:

beans.xml

If the XML metadata file contains <context:annotation-config>, the tag activates detection of @Required and @Autowired, JSR-250 @PostConstruct, @PostDestroy, @PreDestroy and @Resource, @EJB, @PersistenceContext, etc) If the XML metadata contains <context:component-scan >, the context scans the classpath for annotated components that will be auto-registered Spring beans: @Component, @Repository, @Service, @Controller, @RestController, @ControllerAdvice and @Configuration. This tag requires <context:annotation-config> to be on. The equivalent annotation is @ComponentScan(“com.in28minutes.springboot”). The <context:component-scan> element has an annotation-config attribute; however, @ComponentScan annotation does not. This is because in almost all cases when using @ComponentScan, default annotation config processing (e.g. processing @Autowired) is assumed. Furthermore, when using AnnotationConfigApplicationContext, annotation config processors are always registered, meaning that any attempt to disable them at the @ComponentScan level would be ignored.

Java-based Configuration Metadata

Java-based configuration is semantically equivalent with XML-based configuration and it is an alternative to it, or it can be used together with it.

@Configuration

The equivalent of the XML bean definition file is a Java class annotated with @Configuration. The @Configuration annotation indicates that the class it annotates is a configuration class that will provide beans to the Spring application context. The class must expose one or more methods annotated with @Bean. A @Bean-annotated method is the equivalent of an <bean> element in an Spring XML configuration file. The Spring container will invoke those methods to obtain the bean definitions.

For Java-based configuration, @Configuration/@Bean. RETURN_HERE.

@Configuration triggers the configuration of the Spring infrastructure.

Annotation-based Configuration

Annotation-based configuration refers to the possibility of using Java annotations declared in the component class, on the relevant class, method and field declaration, to express the same semantics, such as dependency on another component, that would otherwise be expressed in XML-based configuration.

Spring Components

Also known as Spring beans.

Component Definition

XML-based Component Definition

When XML-based metadata is used, Spring components are defined using a <bean> element:

<beans ...>
    <bean name="red" class="playground.Red"/>
</beans>

One essential element of component definition is the specification of the component's dependencies, using the ref attribute. Once the dependencies are specified in the configuration metadata, the Spring IoC container automatically injects the dependences into all its managed components. For XML-based metadata, dependencies of a component can be injected via constructor or via setter.

This is an example of constructor injection:

<bean name="blue" class="playground.Blue">
  <constructor-arg ref = "red"/>
</bean>

The corresponding component Java class is:

public class Blue {
  private Red red;
  ...
  public Blue(Red red) {
    this.red = red;
    ...
  }
  ...
}

This is an example of setter injection:

<bean name="green" class="playground.Green">
  <property ref = "red"/>
</bean>

The corresponding component Java class is:

public class Green {
  private Red red;
  ...
  public void setRed(Red red) {
    this.red = red;
  }
  ...
}

Note that dependencies are injected only into container-managed components. Components created with new are not managed by the container, so they will not have their dependencies injected. The dependency transitive dependency injection is triggered when the component is obtained from the container as follows:

ApplicationContext context = ...

// this component will get its "red" dependency injected by the container
Blue blue = (Blue)context.getBean("blue");

Java-based Component Definition

Components can also be declared using stereotype annotations. A stereotype annotation denotes the role of the annotated bean in the overall architecture at a conceptual, rather than implementation, level:

Component Lifecycle

Component Scope

Singleton

Component Detection

Auto-detection is ...

Component Scan

Spring IoC Container

The Spring IoC container is also referred to as the core container. The container is a pool of beans created in a memory space by the framework when the application starts up. Some of the beans, such as the singletons, are instantiated right away, when the container is created and started. Other beans are lazily loaded: unless the bean is requested by the application or some other beans as part of their dependency graph, the framework will not instantiate the bean. The container exposes an API that has methods to query these beans.

The simplest type of container is a bean factory, described by the BeanFactory interface. A bean factory provided dependency injection to its beans, initialization and destroy callback invocations.

An application context, described by the ApplicationContext interface, extends a bean factory, so anything a bean factory can do, the application context can do too. Additionally, an application context provides aspects, and application events. The Spring Framework comes with several types of application context implementations:

  • ClassPathXmlApplicationContext is a standalone XML application context that reads the the configuration metadata from XML files from the classpath.
  • FileSystemXmlApplicationContext is a standalone application context that reads the the configuration metadata from XML files loaded from the file system or from URLs, interpreting plain paths as relative file system location.
  • XmlWebApplicationContext.
  • AnnotationConfigApplicationContext is a standalone application context that accepts @Configuration-annotated classes, as well as stereotype-annotated classes and JSR-330 compliant classes using javax.inject annotations as input. In case of multiple @Configuration classes, @Bean methods defined in later classes will override those defined in earlier classes. This can be leveraged to deliberately override certain bean definitions via an extra @Configuration class. Component classes can be registered one by one using register(Class), or they can be detected via the component scan mechanism, triggered by scan(String) method. This application context is used by the Spring Boot applications.

A "classic" Spring Framework application explicitly creates its own application context, usually in its own main class:

public class Main {

    static ApplicationContext APPLICATION_CONTEXT = new ClassPathXmlApplicationContext("some-beans.xml");

    public static void main(String[] args) {
        ...
    }
}

One improvement brought forward by Spring Boot is that Spring Boot applications are not required to do that. The Spring Boot runtime transparently creates the application context.

How to I find an application context that already exists?