UNIT-2 Spring Board
UNIT-2 Spring Board
Till now we have been using XML for writing Spring configurations. Spring also supports
Annotations for configuration. And the best part is that, both of them can also co-exist in
the same project.
Auto Scanning: This enable Spring to auto create beans of the required
classes and register with container for usage by eliminating the
explicit <bean> definitions in the XML file.
1. spring " context " namespace has "annotation-config" tag and hence
context namespace has to be included in the declaration
1. @SpringBootApplication Annotation
This annotation is used to mark the main class of a Spring Boot
application. It encapsulates @SpringBootConfiguration,
@EnableAutoConfiguration, and @ComponentScan annotations
with their default attributes.
@SpringBootApplication
// Class
public class DemoApplication {
// Main driver method
public static void main(String[] args)
{
SpringApplication.run(DemoApplication.class, args);
}
}
2. @SpringBootConfiguration Annotation
3. @EnableAutoConfiguration Annotation
This annotation auto-configures the beans that are
present in the classpath. It simplifies the developer’s work by
assuming the required beans from the classpath and configure it to run the
application. This annotation is part of the spring boot framework.
@Configuration
@EnableAutoConfiguration
4. @ComponentScan Annotation
@ComponentScan tells Spring in which packages you have annotated
classes that should be managed by Spring.
So, for example, if you have a class annotated with @Controller which is in a
package that is not scanned by Spring, you will not be able to use it as a
Spring controller.
// Main class
public class Application {
SpringApplication.run(Application.class, args);
}
}
@Configuration
@ConditionalOnClass(MongoDBService.class)
class MongoDBConfiguration {
// Insert code here
}
7. @ConditionalOnProperty Annotation
These annotations are used to let configuration be included based on the
presence and value of a Spring Environment property.
@Bean
@ConditionalOnProperty(name = "usemongodb", havingValue = "local")
DataSource
dataSource()
{
// Insert code here
}
@Bean
@ConditionalOnProperty(name = "usemongodb",
havingValue = "prod")
DataSource
dataSource()
{
// Insert code here
}
8. @ConditionalOnResource Annotation
These annotations are used to let configuration be included only when a
specific resource is present in the classpath.
@ConditionalOnResource(resources = "classpath:mongodb.properties")
Properties
additionalProperties()
{
// Insert code here
}
9. @ConditionalOnExpression Annotation
These annotations are used to let configuration be included based on the
result of a SpEL (Spring Expression Language) expression.
@Bean
@ConditionalOnExpression("${env} && ${havingValue == 'local'}")
DataSource dataSource()
{
// Insert code here
}
10. @ConditionalOnCloudPlatform Annotation
These annotations are used to let configuration be included when the
specified cloud platform is active.
@Configuration
@ConditionalOnCloudPlatform(CloudPlatform.CLOUD_FOUNDRY)
If Autowiring is enabled, Spring container automatically initializes the dependencies of that bean.
There is no need to provide explicit <property > or <constructor-arg> with ref tags in the bean
definition for object dependencies.
no (no autowiring)
byName
byType
constructor
autodetect
Mode Description
Bean dependency is autowired based on the property name
If the matching bean does not exist in the container then bean
byName will remain unwired
It internally uses setter injection
byName
It uses the name of the bean for injecting dependencies. However, it
requires that the name of the property and bean must be the same.
(City in the above class) Mention an
attribute autowire value "byName". It invokes the setter method internally for
autowiring.
byType
It injects the dependency according to the type of the bean. It looks up in the
configuration file for the class type of the property. If it finds a bean that
matches, it injects the property. If not, the program throws an error. The
names of the property and bean can be different in this case. It invokes the
setter method internally for autowiring.
<bean id="state" class="sample.State">
<property name="name" value="UP" />
</bean>
<bean id="city" class="sample.City" autowire="byType"></bean>
constructor
It injects the required dependencies by invoking the constructor. It works
similar to the “byType” mode but it looks for the class type of the constructor
arguments. If none or more than one bean are detected, then it throws an
error, otherwise, it autowires the “byType” on all constructor arguments.
No
This mode tells the framework that autowiring is not supposed to be done. It
is the default mode used by Spring.
<bean id="state" class="sample.State">
<property name="name" value="UP" />
</bean>
<bean id="city" class="sample.City"></bean>
Bean Scopes
Singleton Scope:
package bean;
// Create a getter method so that the user can get the set value
public String getName()
{
return name;
}
}
package driver;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import bean.HelloWorld;
// Now compare the references to see // whether they are pointing to the
// same object or different object
System.out.println(
"'Geeks1' and 'Geeks2'" + " are referring" + "to the same object: "
+( Geeks1 == Geeks2));
}
}
Output :
When we call the getName() method by using the reference of ‘Geeks1’ and
‘Geeks2’, then we are getting the same outputs. This means that both the
reference is calling the getName() method of the same object. Furthermore,
when we are comparing the reference ‘Geeks1’ and ‘Geeks2’ then output is
“true” which means the same object is shared between ‘Geeks1’ and
‘Geeks2’.
Prototype Scope:
a
If the scope is declared prototype, then spring IOC container will create
new instance of that bean every time a request is made
for that specific bean. A request can be made to the bean instance
either programmatically using getBean() method or by XML for Dependency
Injection of secondary type. Generally, we use the prototype scope for all
beans that are stateful, while the singleton scope is used for the stateless
beans.
package driver;
import org.springframework
.context.ApplicationContext;
import org.springframework.context.support
.ClassPathXmlApplicationContext;
import bean.HelloWorld;
}
}
Singleton Prototype
Same object is shared for each request For each new request a new instance is
made for that bean. i.e. The same object is created. i.e. A new object is created
returned each time it is injected. each time it is injected.
Singleton scope should be used for While prototype scope is used for all
stateless beans. beans that are stateful
<web-app>
...
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
...
</web-app>
Request scope
Consider the following XML configuration for a bean definition:
Session Scope
Consider the following XML configuration for a bean definition:
When using annotation-driven components or Java configuration, you can use the @SessionScope
annotation to assign a component to the session scope.
@SessionScope
@Component
public class UserPreferences {
// ...
}
Application Scope
Consider the following XML configuration for a bean definition:
The Spring container creates a new instance of the AppPreferences bean by using the
appPreferences bean definition once for the entire web application. That is, the appPreferences
bean is scoped at the ServletContext level and stored as a regular ServletContext attribute. This is
somewhat similar to a Spring singleton bean but differs in two important ways: It is a singleton per
ServletContext, not per Spring ApplicationContext (for which there may be several in any given web
application), and it is actually exposed and therefore visible as a ServletContext attribute.
When using annotation-driven components or Java configuration, you can use the
@ApplicationScope annotation to assign a component to the application scope. The following
example shows how to do so:
@ApplicationScope
@Component
public class AppPreferences {
// ...
}
Logging
A good logging infrastructure is necessary for any software project. It helps
in understanding what’s going on with the application. It also to trace any
unusual incident or error present in the project.
Spring Boot’s default configurations provides a support for the use of Java Util Logging,
Log4j2, and Logback. Using these, we can configure the console logging as well as file
logging.
The default Spring Boot Log format gives you the following information:
Date and Time that gives the date and time of the log
Log level shows INFO, ERROR or WARN
Process ID
The --- which is a separator
Thread name is enclosed within the square brackets []
Logger Name that shows the Source class name
Console Log Output
The default log messages will print to the console window. By default, “INFO”,
“ERROR” and “WARN” log messages will print in the log file.
If you have to enable the debug level log, add the debug flag on starting your
application using the command shown below
java –jar demo.jar –debug
You can also add the debug mode to your application.properties file as shown here −
debug = true
Note − files will rotate automatically after reaching the size 10 MB.
Log Levels
Spring Boot supports all logger levels such as “TRACE”, “DEBUG”, “INFO”, “WARN”,
“ERROR”, “FATAL”, “OFF”. You can define Root logger in the application.properties
file as shown below −
logging.level.root = WARN
Note − Logback does not support “FATAL” level log. It is mapped to the “ERROR”
level log.
Configure Logback
Logback supports XML based configuration to handle Spring Boot Log
configurations. Logging configuration details are configured in logback.xml file. The
logback.xml file should be placed under the classpath.
You can configure the ROOT level log in Logback.xml file using the code given
below
<?xml version = "1.0" encoding = "UTF-8"?>
<configuration>
<root level = "INFO">
</root>
</configuration>
You can configure the console appender in Logback.xml file given below.
<?xml version = "1.0" encoding = "UTF-8"?>
<configuration>
<appender name = "STDOUT" class =
"ch.qos.logback.core.ConsoleAppender"></appender>
<root level = "INFO">
<appender-ref ref = "STDOUT"/>
</root>
</configuration>
The code for complete logback.xml file is given below. You have to place this in the
class path.
<?xml version = "1.0" encoding = "UTF-8"?>
<configuration>
<appender name = "STDOUT" class =
"ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>[%d{yyyy-MM-dd'T'HH:mm:ss.sss'Z'}] [%C] [%t] [%L] [%-5p]
%m%n</pattern>
</encoder>
</appender>
The code given below shows how to add the slf4j logger in Spring Boot
main class file.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class LogController {
// creating a logger
Logger logger
= LoggerFactory.getLogger(LogController.class);
Spring AOP module provides interceptors to intercept an application. For example, when a
method is executed, you can add extra functionality before or after the method execution.
Spring: It uses XML based configuration for implementing AOP,
also it uses annotations which are interpreted by using a library
supplied by AspectJ for parsing and matching.
AOP breaks the program logic into distinct parts. Each part is called a
concern. It is used to increase modularity by cross-cutting
concerns.
A cross-cutting concern is a concern that can affect the whole application and
should be centralized in one location in code as possible,
such as transaction management, authentication, logging, security etc.
Why use AOP?
class A{
public void m1(){...}
public void m2(){...}
public void m3(){...}
public void m4(){...}
public void m5(){...}
public void n1(){...}
public void n2(){...}
public void p1(){...}
public void p2(){...}
public void p3(){...}
}
There are 5 methods that starts from m, 2 methods that starts from n and
3 methods that starts from p.
o Join point
o Advice
o Pointcut
o Introduction
o Target Object
o Aspect
o Interceptor
o AOP Proxy
o Weaving
Join point
any point in your program such as
Join point is
method execution, exception handling, field
access etc. But Spring AOP currently supports only method execution
join points
Aspect
This is a module which has a set of APIs providing requirements. For example, a
logging module would be called AOP aspect for logging. An application can have any
number of aspects depending on the requirement.
For Example, we can have security AOP, transaction AOP, notification AOP.
Spring supports the @AspectJ annotation style approach and the schema-
based approach to implement custom aspects.
XML Schema based
Aspects are implemented using the regular classes along with XML based
configuration.
@AspectJ based
@AspectJ refers to a style of declaring aspects as regular Java classes annotated
with Java 5 annotations.
Advice
Pointcut
This is a set of one or more join points where an advice should be executed. You
can specify pointcuts using expressions or patterns as we will see in our AOP
examples.
Introduction
An introduction allows you to add new methods or attributes to the existing classes.
Target object
The object being advised by one or more aspects. This object will always be a
proxied object, also referred to as the advised object.
Weaving
Weaving is the process of linking aspects with other application types or objects to
create an advised object. This can be done at compile time, load time, or at runtime.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
@Service
@Transactional
public class ProductService {
private final ProductRepository productRepository;
public class A {
public A(B b){
....
}
}
public class B {
public B(A b){
....
}
}
One possible solution is to edit the source code of some classes to be configured
by setters rather than constructors. Alternatively, avoid constructor injection and
use setter injection only. In other words, although it is not recommended, you
can configure circular dependencies with setter injection.
7. exception Handling in
Spring boot Rest API projects
Handle proper exceptions and custom error messages for RESTful Web Services
developed using Spring Boot.
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
You need not put all your @Configuration into a single class. The @Import
annotation can be used to import additional configuration classes.
For example:
@Configuration
public class DataSourceConfig {
@Bean
public DataSource dataSource() {
return new DriverManagerDataSource(...);
}
}
@Configuration
@Import({ DataSourceConfig.class, TransactionConfig.class })
public class AppConfig extends ConfigurationSupport {
// @Bean methods here can reference @Bean methods in DataSourceConfig
or TransactionConfig
}