Spring
Spring
1 @Required
2 @Autowired
3 @Qualifier
@Configuration
public class HelloWorldConfig {
@Bean
public HelloWorld helloWorld(){
return new HelloWorld();
}
}
<beans>
<bean id = "helloWorld" class = "com.tutorialspoint.HelloWorld" />
</beans>
Here, the method name is annotated with @Bean works as bean ID and it creates
and returns the actual bean. Your configuration class can have a declaration for
more than one @Bean. Once your configuration classes are defined, you can load
and provide them to Spring container using AnnotationConfigApplicationContext as
follows −
You can import above Bean declaration in another Bean Declaration as follows −
@Configuration
@Import(ConfigA.class)
public class ConfigB {
@Bean
public B a() {
return new A();
}
}
Now, rather than needing to specify both ConfigA.class and ConfigB.class when
instantiating the context, only ConfigB needs to be supplied as follows −
@Configuration
public class AppConfig {
@Bean
public Foo foo() {
return new Foo(bar());
}
@Bean
public Bar bar() {
return new Bar();
}
}
Here, the foo bean receives a reference to bar via the constructor injection. Now
let us look at another working example.
@Configuration
public class AppConfig {
@Bean
@Scope("prototype")
public Foo foo() {
return new Foo();
}
}
@Service
Annotate all your service classes with @Service. All your business logic should be in
Service classes.
@Service
public class CompanyServiceImpl implements CompanyService {
...
}
@Repository
Annotate all your DAO classes with @Repository. All your database access logic
should be in DAO classes.
@Repository
public class CompanyDAOImpl implements CompanyDAO {
...
}
@Component
Annotate your other components (for example REST resource classes) with
@Component.
@Component
public class ContactResource {
...
}
@Component is a generic stereotype for any Spring-managed component.
@Repository, @Service, and @Controller are specializations of @Component for
more specific use cases, for example, in the persistence, service, and presentation
layers, respectively.
@Autowired
Let Spring auto-wire other beans into your classes using @Autowired annotation.
@Service
public class CompanyServiceImpl implements CompanyService {
@Autowired
private CompanyDAO companyDAO;
...
}
Spring beans can be wired by name or by type.
@Transactional
Configure your transactions with @Transactional spring annotation.
@Service
public class CompanyServiceImpl implements CompanyService {
@Autowired
private CompanyDAO companyDAO;
@Transactional
public Company findByName(String name) {
@Component
@Scope("request")
public class ContactResource {
...
}
Similarly, you can annotate your component with @Scope("prototype") for beans
with prototype scopes.
@Controller
Annotate your controller classes with @Controller.
@Controller
public class CompanyController {
...
}
@RequestMapping
You use the @RequestMapping spring annotation to map URLs onto an entire class
or a particular handler method. Typically the class-level annotation maps a specific
request path (or path pattern) onto a form controller, with additional method-level
annotations narrowing the primary mapping.
@Controller
@RequestMapping("/company")
public class CompanyController {
@Autowired
private CompanyService companyService;
...
}
@PathVariable
You can use the @PathVariable spring annotation on a method argument to bind it
to the value of a URI template variable. In our example below, a request path of
/company/techferry will bind companyName variable with 'techferry' value.
@Controller
@RequestMapping("/company")
public class CompanyController {
@Autowired
private CompanyService companyService;
@RequestMapping("{companyName}")
public String getCompany(Map<String, Object> map,
@PathVariable String companyName) {
Company company = companyService.findByName(companyName);
map.put("company", company);
return "company";
}
...
}
@RequestParam
You can bind request parameters to method variables using spring annotation
@RequestParam.
@Controller
@RequestMapping("/company")
public class CompanyController {
@Autowired
private CompanyService companyService;
@RequestMapping("/companyList")
public String listCompanies(Map<String, Object> map,
@RequestParam int pageNum) {
map.put("pageNum", pageNum);
map.put("companyList", companyService.listCompanies(pageNum));
return "companyList";
}
...
}
Similarly, you can use spring annotation @RequestHeader to bind request headers.
@ModelAttribute
An @ModelAttribute on a method argument indicates the argument should be
retrieved from the model. If not present in the model, the argument should be
instantiated first and then added to the model. Once present in the model, the
argument's fields should be populated from all request parameters that have
matching names. This is known as data binding in Spring MVC,
@Controller
@RequestMapping("/company")
public class CompanyController {
@Autowired
private CompanyService companyService;
@RequestMapping("/add")
public String saveNewCompany(@ModelAttribute Company company) {
companyService.add(company);
return "redirect:" + company.getName();
}
...
}
@SessionAttributes
@SessionAttributes spring annotation declares session attributes. This will typically
list the names of model attributes which should be transparently stored in the
session, serving as form-backing beans between subsequent requests.
@Controller
@RequestMapping("/company")
@SessionAttributes("company")
public class CompanyController {
@Autowired
private CompanyService companyService;
...
}
@SessionAttribute works as follows:
The following listing illustrate these concepts. It is also an example for pre-
populating Model objects.
@Controller
@RequestMapping("/owners/{ownerId}/pets/{petId}/edit")
@SessionAttributes("pet")
public class EditPetForm {
@ModelAttribute("types")
@PreAuthorize
Using Spring Security @PreAuthorize annotation, you can authorize or deny a
functionality. In our example below, only a user with Admin role has the access to
delete a contact.
@Transactional
@PreAuthorize("hasRole('ROLE_ADMIN')")
public void removeContact(Integer id) {
contactDAO.removeContact(id);
}
@Controller
@RequestMapping("/foo", method=RequestMethod.POST)
public void processFoo(@Valid Foo foo) { /* ... */ }
Spring MVC will validate a @Valid object after binding so-long as an appropriate
Validator has been configured.
We localize validation error messages for the email field, so put the following
key=value pairs in messages.properties file:
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>SpringMvcFormValidationExample</display-name>
<servlet>
<servlet-name>SpringController</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>SpringController</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
With Spring MVC, there are 3 different ways to perform validation : using
annotation, manually, or a mix of both.
...
Method 1 : If you have Spring 3.x+ and simple validation to do,
use javax.validation.constraintsannotations.
@NotNull
private String name;
...
@RequestMapping(value="/user", method=RequestMethod.POST)
if (result.hasErrors()){
// do something
else {
// do something else
Notice the @Valid : if the user happens to have a null name, result.hasErrors() will
be true.
Method 2 : If you have complex validation (like big business validation logic,
conditional validation across multiple fields, etc.), or for some reason you cannot
use method 1, use manual validation. It is a good practice to separate the
controller’s code from the validation logic. Don't create your validation class(es)
from scratch, Spring provides a
handy org.springframework.validation.Validatorinterface (since Spring 2).
...
and you want to do some "complex" validation like : if the user's age is under 18,
responsibleUser must not be null and responsibleUser's age must be over 21.
@Override
return User.class.equals(clazz);
@Override
if(user.getName() == null) {
errors.rejectValue("name", "your_error_code");
@RequestMapping(value="/user", method=RequestMethod.POST)
userValidator.validate(user, result);
if (result.hasErrors()){
// do something
else {
// do something else
Method 3 : Why not using a combination of both methods? Validate the simple
stuff, like the "name" attribute, with annotations (it is quick to do, concise and
more readable). Keep the heavy validations for validators (when it would take
hours to code custom complex validation annotations, or just when it is not possible
to use annotations). I did this on a former project, it worked like a charm, quick &
easy.
Bullet Points
Bean LifeCycle :
When bean is initialized it might require to perform some activity before it can
come into useable state(State in which application can use it) and when bean is
getting destroyed there might be some cleanup activity required for given bean.
These activities are known as bean Lifecycle.
Standard bean lifecycle interfaces & there standard order of execution are given
below..
1- IoC container will look for the configuration metadata of given Bean.
2- Once find, container will create the instance of Bean(Using reflection API).
3- After instance creation dependency will be injected(DI).
In case Bean class has custom init method defined(via init-method attribute)
When Bean Factory is getting shut down following lifecycle methods will be
executed.
Below is a simple class that will be configured as spring bean and for post-init and
pre-destroy methods, we are using @PostConstruct and @PreDestroy annotations.
package com.journaldev.spring.service;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
public class MyService {
@PostConstruct
public MyService(){
@PreDestroy
Let’s see how we will configure our beans in spring context file.
<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.xsd">
<bean name="employeeService"
class="com.journaldev.spring.service.EmployeeService">
</bean>
<bean name="myEmployeeService"
class="com.journaldev.spring.service.MyEmployeeService"
init-method="init" destroy-method="destroy">
</bean>
<bean
class="org.springframework.context.annotation.CommonAnnotationBeanPostProce
ssor" />
</beans>
XMLBeanFactory
Spring configuration file is an XML file. This file contains the classes information and
describes how these classes are configured and introduced to each other.
The Spring IoC is responsible for creating the objects, managing them (with
dependency injection (DI)), wiring them together, configuring them, as also
managing their complete lifecycle.
Dependency Injection
What are the different types of IoC (dependency injection)?
You can use both Constructor-based and Setter-based Dependency Injection. The
best solution is using constructor arguments for mandatory dependencies and
setters for optional dependencies.
Spring Beans
The Spring Beans are Java Objects that form the backbone of a Spring application.
They are instantiated, assembled, and managed by the Spring IoC container. These
beans are created with the configuration metadata that is supplied to the container,
for example, in the form of XML <bean/> definitions.
Beans defined in spring framework are singleton beans. There is an attribute in
bean tag named "singleton" if specified true then bean becomes singleton and if
set to false then the bean becomes a prototype bean. By default it is set to true.
So, all the beans in spring framework are by default singleton beans.
A Spring Bean definition contains all configuration metadata which is needed for the
container to know how to create a bean, its lifecycle details and its dependencies.
There are three important methods to provide configuration metadata to the Spring
Container:
XML based configuration file.
Annotation-based configuration
How do you define the scope of a bean?
When defining a <bean> in Spring, we can also declare a scope for the bean. It
can be defined through the scope attribute in the bean definition. For example,
when Spring has to produce a new bean instance each time one is needed, the
bean’s scope attribute to be prototype . On the other hand, when the same
instance of a bean must be returned by Spring every time it is needed, the the
bean scope attribute must be set to singleton .
There are five scoped provided by the Spring Framework supports following five
scopes:
In singleton scope, Spring scopes the bean definition to a single instance per
Spring IoC container.
In prototype scope, a single bean definition has any number of object
instances.
In request scope, a bean is defined to an HTTP request. This scope is valid only
in a web-aware Spring ApplicationContext.
In session scope, a bean definition is scoped to an HTTP session. This scope is
also valid only in a web-aware Spring ApplicationContext.
In global-session scope, a bean definition is scoped to a global HTTP session.
This is also a case used in a web-aware Spring ApplicationContext.
The default scope of a Spring Bean is Singleton .
There are different scenarios where you Dependency Injections are useful.
There were scenarios where you don’t need dependency injections e.g.
How you will decide when to use prototype scope and when singleton
scope bean?
You should use the prototype scope for all beans that are stateful and the singleton
scope should be used for stateless beans.
v.v.imp
To call a Stored procedure in Spring framework you need to create Class which
should extends StoredProcedure class. Take the example of getting Employee
Details by Employee Id. package com.mytest.spring.storeproc
import java.sql.ResultSet;
import java.sql.Types;
import java.util.HashMap;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.jdbc.core.SqlOutParameter;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.object.StoredProcedure;
public class EmployeeInfo extends StoredProcedure {
You just need to call the execute method from the DAO layer.
- With ApplicationContext more than one config files are possible while only one
config file or .xml file is possible with BeanFactory.
- ApplicationContext publishes events to beans that are registered as listeners while
BeanFactory doesn't support this
- ApplicationContext support internationalization messages, application life-cycle
events, validation and many enterprise services like JNDI access, EJB integration,
remoting etc. while BeanFactory doesn't support any of these.
Instantiate - First the spring container finds the bean's definition from the
XML file and instantiates the bean..
Populate properties - Using the dependency injection, spring populates all
of the properties as specified in the bean definition..
Pre Initialization - Also called postprocess of bean. If there are any bean
BeanPostProcessors associated with the bean, Spring calls
postProcesserBeforeInitialization() method.
Can we use more than one configuration file for our Spring project?
Problem
In a large project structure, the Spring’s bean configuration files are located in
different folders for easy maintainability and modular. For example, Spring-
Common.xml in common folder, Spring-Connection.xml in connection
folder, Spring-ModuleA.xml in ModuleA folder…and etc.
You may load multiple Spring bean configuration files in the code :
ApplicationContext context =
"Spring-Connection.xml","Spring-ModuleA.xml"});
project-classpath/Spring-Common.xml
project-classpath/Spring-Connection.xml
project-classpath/Spring-ModuleA.xml
Solution
The above ways are lack of organizing and error prone, the better way should be
organized all your Spring bean configuration files into a single XML file. For
example, create a Spring-All-Module.xml file, and import the entire Spring bean
files like this :
File : Spring-All-Module.xml
<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.5.xsd">
<import resource="common/Spring-Common.xml"/>
<import resource="connection/Spring-Connection.xml"/>
<import resource="moduleA/Spring-ModuleA.xml"/>
</beans>
ApplicationContext context =
new ClassPathXmlApplicationContext(Spring-All-Module.xml);
project-classpath/Spring-All-Module.xml
Note
In Spring3, the alternative solution is using JavaConfig @Import.
Explain Spring MVC flow with a simple example e.g. starting from
Container receives request and forward to your Java application ?