Springframework
Contents
Spring Data
Spring Data’s mission is to provide a familiar and consistent, Spring-based programming model for data access while still retaining the special traits of the underlying data store.
It makes it
- easy to use data access technologies,
- relational and non-relational databases,
- map-reduce frameworks,
- and cloud-based data services.
This is an umbrella project which contains many subprojects that are specific to a given database. The projects are developed by working together with many of the companies and developers that are behind these exciting technologies.
Spring Data JPA
Spring Data JPA, part of the larger Spring Data family, makes it easy to easily implement JPA based repositories. This module deals with enhanced support for JPA based data access layers. It makes it easier to build Spring-powered applications that use data access technologies.
Inversion of Control
What is Inversion of Control?
Inversion of Control is a principle in software engineering by which the control of objects or portions of a program is transferred to a container or framework. It’s most often used in the context of object-oriented programming.
By contrast with traditional programming, in which our custom code makes calls to a library, IoC enables a framework to take control of the flow of a program and make calls to our custom code. To enable this, frameworks use abstractions with additional behavior built in. If we want to add our own behavior, we need to extend the classes of the framework or plugin our own classes.
The advantages of this architecture are:
- decoupling the execution of a task from its implementation
- making it easier to switch between different implementations
- greater modularity of a program
- greater ease in testing a program by isolating a component or mocking its dependencies and allowing components to communicate through contracts
Inversion of Control(IoC) can be achieved through various mechanisms such as: Strategy design pattern, Service Locator pattern, Factory pattern, and Dependency Injection (DI).
Dependency Injection
What is Dependency Injection?
Dependency injection is a pattern through which to implement IoC, where the control being inverted is the setting of object’s dependencies.
The act of connecting objects with other objects, or “injecting” objects into other objects, is done by an assembler rather than by the objects themselves.
Here’s how you would create an object dependency in traditional programming:
public class Store {
private Item item;
public Store() {
item = new ItemImpl1();
}
}
In the example above, we need to instantiate an implementation of the Item interface within the Store class itself.
By using DI, we can rewrite the example without specifying the implementation of Item that we want:
public class Store {
private Item item;
public Store(Item item) {
this.item = item;
}
}
The Spring IoC Container
An IoC container is a common characteristic of frameworks that implement IoC.
In the Spring framework, the IoC container is represented by the interface ApplicationContext. The Spring container is responsible for instantiating, configuring and assembling objects known as beans, as well as managing their lifecycle.
The Spring framework provides several implementations of the ApplicationContext interface
- — ClassPathXmlApplicationContext and FileSystemXmlApplicationContext for standalone applications,
- — WebApplicationContext for web applications.
In order to assemble beans, the container uses configuration metadata, which can be in the form of XML configuration or annotations.
Here’s one way to manually instantiate a container:
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Dependency Injection in Spring
To set the item attribute in the example above, we can use metadata. Then, the container will read this metadata and use it to assemble beans at runtime.
Dependency Injection in Spring can be done through constructors, setters or fields.
Dependency Injection Types
Constructor-Based Dependency Injection
In the case of constructor-based dependency injection, the container will invoke a constructor with arguments each representing a dependency we want to set.
Spring resolves each argument primarily by type, followed by name of the attribute and index for disambiguation. Let’s see the configuration of a bean and its dependencies using annotations:
@Configuration
public class AppConfig {
@Bean
public Item item1() {
return new ItemImpl1();
}
@Bean
public Store store() {
return new Store(item1());
}
}
The @Configuration annotation indicates that the class is a source of bean definitions. Also, we can add it to multiple configuration classes.
The @Bean annotation is used on a method to define a bean. If we don’t specify a custom name, the bean name will default to the method name.
For a bean with the default singleton scope, Spring first checks if a cached instance of the bean already exists and only creates a new one if it doesn’t. If we’re using the prototype scope, the container returns a new bean instance for each method call.
Another way to create the configuration of the beans is through XML configuration:
<bean id="item1" class="org.baeldung.store.ItemImpl1" />
<bean id="store" class="org.baeldung.store.Store">
<constructor-arg type="ItemImpl1" index="0" name="item" ref="item1" />
</bean>
Setter-Based Dependency Injection
For setter-based DI, the container will call setter methods of our class, after invoking a no-argument constructor or no-argument static factory method to instantiate the bean. Let’s create this configuration using annotations:
@Bean
public Store store() {
Store store = new Store();
store.setItem(item1());
return store;
}
We can also use XML for the same configuration of beans:
<bean id="store" class="org.baeldung.store.Store">
<property name="item" ref="item1" />
</bean>
Constructor-based and setter-based types of injection can be combined for the same bean. The Spring documentation recommends using constructor-based injection for mandatory dependencies, and setter-based injection for optional ones.
Field-Based Dependency Injection
In case of Field-Based DI, we can inject the dependencies by marking them with an @Autowired annotation:
public class Store {
@Autowired
private Item item;
}
While constructing the Store object, if there’s no constructor or setter method to inject the Item bean, the container will use reflection to inject Item into Store.
We can also achieve this using XML configuration.
This approach might look simpler and cleaner but is not recommended to use because it has a few drawbacks such as:
- This method uses reflection to inject the dependencies, which is costlier than constructor-based or setter-based injection
- It’s really easy to keep adding multiple dependencies using this approach. If you were using constructor injection having multiple arguments would have made us think that the class does more than one thing which can violate the Single Responsibility Principle.
More information on @Autowired annotation can be found in Wiring In Spring article.
Autowiring Dependencies
Wiring allows the Spring container to automatically resolve dependencies between collaborating beans by inspecting the beans that have been defined.
There are four modes of autowiring a bean using an XML configuration:
- no: the default value – this means no autowiring is used for the bean and we have to explicitly name the dependencies
- byName: autowiring is done based on the name of the property, therefore Spring will look for a bean with the same name as the property that needs to be set
- byType: similar to the byName autowiring, only based on the type of the property. This means Spring will look for a bean with the same type of the property to set. If there’s more than one bean of that type, the framework throws an exception.
- constructor: autowiring is done based on constructor arguments, meaning Spring will look for beans with the same type as the constructor arguments
For example, let’s autowire the item1 bean defined above by type into the store bean:
@Bean(autowire = Autowire.BY_TYPE)
public class Store {
private Item item;
public setItem(Item item){
this.item = item;
}
}
We can also inject beans using the @Autowired annotation for autowiring by type:
public class Store {
@Autowired
private Item item;
}
If there’s more than one bean of the same type, we can use the @Qualifier annotation to reference a bean by name:
public class Store {
@Autowired
@Qualifier("item1")
private Item item;
}
Now, let’s autowire beans by type through XML configuration:
<bean id="store" class="org.baeldung.store.Store" autowire="byType"> </bean>
Next, let’s inject a bean named item into the item property of store bean by name through XML:
<bean id="item" class="org.baeldung.store.ItemImpl1" />
<bean id="store" class="org.baeldung.store.Store" autowire="byName">
</bean>
We can also override the autowiring by defining dependencies explicitly through constructor arguments or setters.
Bean scopes
Singleton Scope
When a bean is a singleton, only one shared instance of the bean will be managed, and all requests for beans with an id or ids matching that bean definition will result in that one specific bean instance being returned by the Spring container.
To put it another way, when you define a bean definition and it is scoped as a singleton, then the Spring IoC container will create exactly one instance of the object defined by that bean definition. This single instance will be stored in a cache of such singleton beans, and all subsequent requests and references for that named bean will result in the cached object being returned.
Prototype Scope
The non-singleton, prototype scope of bean deployment results in the creation of a new bean instance every time a request for that specific bean is made (that is, it is injected into another bean or it is requested via a programmatic getBean() method call on the container). As a rule of thumb, you should use the prototype scope for all beans that are stateful, while the singleton scope should be used for stateless beans.
<!-- using spring-beans-2.0.dtd -->
<bean id="accountService" class="com.foo.DefaultAccountService" scope="prototype"/>
<!-- the following is equivalent and preserved for backward compatibility in spring-beans.dtd -->
<bean id="accountService" class="com.foo.DefaultAccountService" singleton="false"/>
Other scopes
The other scopes, namely request, session, and global session are for use only in web-based applications (and can be used irrespective of which particular web application framework you are using, if indeed any)
The scopes that are described in the following paragraphs are only available if you are using a web-aware Spring ApplicationContext implementation (such as XmlWebApplicationContext). If you try using these next scopes with regular Spring IoC containers such as the XmlBeanFactory or ClassPathXmlApplicationContext, you will get an IllegalStateException complaining about an unknown bean scope.
Request Scope
<bean id="loginAction" class="com.foo.LoginAction" scope="request"/>
With the above bean definition in place, the Spring container will create a brand new instance of the LoginAction bean using the 'loginAction' bean definition for each and every HTTP request.
Session Scope
<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>
With the above bean definition in place, the Spring container will create a brand new instance of the UserPreferences bean using the 'userPreferences' bean definition for the lifetime of a single HTTP Session.
Global Scope
<bean id="userPreferences" class="com.foo.UserPreferences" scope="globalSession"/>
The global session scope is similar to the standard HTTP Session scope (described immediately above), and really only makes sense in the context of portlet-based web applications.
Lazy Initialized Beans
By default, the container creates and configures all singleton beans during initialization. To avoid this, you can use the lazy-init attribute with value true on the bean configuration:
<bean id="item1" class="org.baeldung.store.ItemImpl1" lazy-init="true" />
As a consequence, the item1 bean will be initialized only when it’s first requested, and not at startup. The advantage of this is faster initialization time, but the trade-off is that configuration errors may be discovered only after the bean is requested, which could be several hours or even days after the application has already been running.