Spring Annotation
Spring Annotation
configuration
Framework software uses the annotations to get the information about the element or
manipulate the elements using reflection API.
From spring 2.5 onwards we can configure Spring beans and their dependencies using
annotations
Spring supplies various types of annotations in its all modules to simplify the spring application
development.
1. Stereotype annotations
2. Auto-wiring annotations
3. Miscellaneous annotations
1. @Component
2. @Service
3. @Repository
4. @Controller
@Service:
It indicates that this class is a service layer class which means, this class contains the main
business logic.
@Repository:-
It indicates that this class is a Data access layer class, i.e. this class contains the data access
logic/ persistence logic.
@Controller:-
It indicates that this class is a controller layer/presentation layer, which contains logic to control
the flow of our application or contains the presentation logic.
Component auto-scanning:
With the component auto-scanning, the spring bean configuration burden is reduced on
developers.
In component auto-scanning container will register a class as a spring bean with the class
name (starting with a small letter ) as its id.
Example:
@Repository
class AccountDao{
Here the above class will be registered as a Spring bean with the Spring container by the id
“accountDao”.
In order to tell the container to register the above class with the different id then we use the
below approach:
@Repository(value="dao")
class AccountDao{
The above configuration will auto-scan all the classes which are annotated with Stereotype
annotations inside the following packages:
com.example;
com.example.dao;
com.example.service;
com.example.utiltity;
Example2 :
If we configure like :
Example:
package com.example;
@Service
public class A{
package com.example.services;
@Component
package com.abc;
@Repository
public class C{
package com.example.repo;
public class D{
Here only A and B classes will be registered with the spring container with the id "a" and "b".
Here C class is in a different package and the D class does not have stereotype annotation. so
they
will not be registered with the container as a spring bean.
Example 2:
Now A, B, and C classes will be registered as a Spring bean with the container.
We Problem:
Let’s register a Java class with the Spring container using Annotations and make it a Spring
bean.
package com.example;
import org.springframework.stereotype.Service;
@Service(value = "a1")
public class A {
applicationContext.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd" >
</beans>
Demo.java:
package com.example;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
A obj = ctx.getBean("a1",A.class);
obj.funA();
Auto-wiring annotations:
1. @Autowired
2. @Quilifier
1. @Autowired
This annotation we can apply on the fields/variable or the setter method or on the
constructor
of a spring bean.
The variable on which we apply the @Autowired annotation must be a reference type
variable. not the primitive variable.
Example:
@Autowired //valid
private Student student;
@Autowired // invalid
private int x;
If we apply @Autowired annotation on the top of the reference variable then no need to
explicitly define the setter method. (setter injection point). at runtime container implicitly
defines the setter method for that field.
If we apply this @Autowire annotation on the reference field, then the container will search
the
"registered bean"(which spring bean is already registered with the container) by using either
byName approach or by using byType approach, and if found then the container will inject
that
Spring bean object to this reference field.
Note:- if we use @Autowired annotation on the top of a reference field then that
dependency will be mandatory.
Here if the Spring bean object is there (registered with the container) then it will be injected
otherwise the field will remain with the null value.
Example:
B.java:-
----------
package com.example;
import org.springframework.stereotype.Service;
@Service
public class B {
}
}
A.java:-
-----------
package com.example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
@Service
public class A {
@Autowired
private B b1;
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
</beans>
Demo.java:
package com.example;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
A obj = ctx.getBean("a",A.class);
obj.funA();
}
}
In the above application if we register one more object of B class as a spring bean using XML
also with different id, then the Spring container will throw an ambiguity exception.
Example
<beans
</beans>
@Autowired
private B b1;
Spring container will first use byName strateg y to search the registered Spring bean, since it
will not found then Spring container will use byType strategy to search the registered Spring
bean, here it will found 2 spring bean one registered using stereotype annotation and another is
registered with XML configuration, and Spring container would not qualify the appropriate bean
to inject so it will raise an ambiguity error.
To solve the above problem we can make use @Qualifier annotation with the specific bean id
which we want to inject.
Example:
@Autowired
@Qualifier("b5") // to choose one spring bean obj among multiple registered obj.
private B b1;
Note:- we can apply the @Autowired annotation on the top of the setter method also, using this
we have more control over the our defined setter method compare to container defined setter
method at runtime. i.e. we can place some other logics also inside our defined setter method.
Miscellaneous annotations:
Example:
@Service
@Scope("prototype")
public class A {
--
}
In order to use these annotation we need to add following dependency inside the pom.xml
file: javax.annotation-api:
Example:
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
Example:
A.java :-
---------
package com.example;
import javax.annotation.PostConstruct;
@Service
public class A {
@Autowired
private B b1;
@PostConstruct
public void setUp() {
System.out.println("inside set up method");
}
@PreDestroy
public void tearDown(){
System.out.println("inside tear down method");
}
3. @Configuration:
From spring 4.x onward we can define a configuration class, instead of spring
configuration file (XML file)
To make a java class as a spring configuration class we need to annotate that class by
using @Configuration annotation.
Example:
@Configuration
public class AppConfig{
Example:
Note:- we can write more than one spring configuration class also.
Example:
@Configuration
public class AppConfig2{
in that case:-
4.@ComponentScan:
Note: this annotation should be used on the spring configuration class only, i.e. the class
which is annotated with @Configuration annotation.
Example:
I Problem:
Creating an Spring application which will make use of Annotation only(Without using XML
file)
A.java:-
---------
package com.example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class A {
@Autowired
private B b1;
B.java:-
---------
package com.example;
import org.springframework.stereotype.Service;
@Service
public class B {
AppConfig.java:-
-------------------
package com.example;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {
Demo.java:-
---------------
package com.example;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
A obj = ctx.getBean("a",A.class);
obj.funA();
}
}
You Problem:
Modify the above application to place @PostConstruct, @Scope as prototype annotations
and call the method of A class object.
5. @Bean:
On which method, we apply this annotation should return any object, spring container
will register the returned object with itself(with container) with the id as method name
itself.
We can define @Bean annotated method either inside @Configuration annotated class
or inside any spring bean class(which is annotated with stereotype annotation and
scanned by the spring container).
While auto-scanning, when container encounters with @Bean annotated method, it will
call that method and register the returned object with the spring container by the id as
the method name itself.
Example:
@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {
@Bean
public B getB(){
B b1=new B();
return b1;
Here the getB() method will be called automatically at the time of scanning and returned
object of that method will be registered with the container with the id "getB".
B b1=new B();
return b1;
With the help of @Bean annotation we can register any predefined classes also with
the container.
Example:
@Bean("clist")
public List<String> getCities(){
cities.add("delhi");
cities.add("chennai");
cities.add("mumbai");
cities.add("kolkata");
return cities;
A.java:
package com.example;
import java.util.List;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class A {
@Autowired
private List<String> cities;
6. @Value:
This annotation is used to inject simple values type variables.
Example:
A.java:-
---------
package com.example;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
@Service
public class A {
@Value("100")
int roll=100;
@Value("Ram")
String name;
@Value("780")
int marks;
Note:- this @Value annotation is not used to supply dummy data as above program.
db.driverName=com.mysql.cj.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/db
db.username=root
db.password=root
Step 2: Now we can inject these values to the simple type variable of our Bean.
Example:
A.java:-
-----------
package com.example;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
@Service
public class A {
@Value("${db.driverName}")
private String dname;
@Value("${db.url}")
private String url;
@Value("${db.username}")
private String uname;
@Value("${db.password}")
private String pass;
Step 3: specify the name of the properties file using @PropertySource annotation on the
top of @Configuration annotated class.
Example:
AppConfig.java:-
-------------------
package com.example;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@ComponentScan(basePackages = "com.example")
@PropertySource("a1.properties")
public class AppConfig {
@Configuration
@ComponentScan(basePackages = "com.example")
@PropertySources({
@PropertySource("a1.properties"),
@PropertySource("a2.properties")
})
public class AppConfig {
Note:- we can read the properties files details by using "Environment" object also, in much
more easier way.
A.java:-
----------
package com.example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
@Autowired
private Environment env;