SpringONELiner

|
Divnesh BLOG
  • Spring is a popular open source Java application development framework which supports developing any kind of Java applications such as standalone applications, web applications, database driven applications and many more.
  • Spring framework helps in developing a loosely coupled application which is simple, easily testable, reusable and maintainable.
  • Inversion of control(IoC) : An application can make loosely coupled by moving the application object life cycle management responsibility to the third party such as a framework.
  • Inversion of Control (IoC) represents the inversion of application responsibility of object's creation, initialization, dependency and destruction from the application to the third party.
  • Dependency Injection(DI) : Spring Framework provides IoC implementation using DI. Spring's Dependency Injection features makes an application loosely coupled by moving object dependencies away from the application to the Spring container.
  • DI is a software design pattern that provides better software design to facilitate loose coupling, reuse and ease of testing.
  • Features : Light weight, loosely coupled, non invasive (POJO), IOC, Spring container, Aspects oriented Programming (AOP).

Continers :
BeanFactory : org.springframework.beans.factory.BeanFactory
ApplicationContext : org.springframework.beans.factory.BeanFactory - inherits the BeanFactory 

features

 

Bean Factory

Application context

Does not support annotation based Dependency Injection.

Support annotation based Dependency Injection.

Does not support enterprise services.

Support enterprise services such as validations, internationalization, etc.


Configuration Metadata

 

XML configuration

 

bean creation :


bean id="reportService" class="com.infosys.service.ReportService"/

reportService --> bean id

com.infosys.service.ReportService --> Fully qualified class name

Access this from java code

"ReportService reportService = (ReportService ) context.getBean("reportService");"

"ReportService reportService = context.getBean(ReportService.class);"

"ReportService reportService = context.getBean("reportService2", ReportService.class);"

Dependency injection:

Constructor : constructor-arg tag This is achieved when the container invokes parameterized constructor to initialize the properties of a class

Primitive values


by name

constructor arg name="totalRecords" value="500" /,

type

constructor arg value="200.00" type = "double"/,

index

constructor arg value="500" index="1" /


public ReportService(double recordsPerPage) {

     this.recordsPerPage = recordsPerPage;

}


Non Primitive : constructor-arg name="master" ref="pdfReportGenerator"/

bean id="pdfReportGenerator" class="com.infosys.demo.PDFReportGenerator"/     

public ReportService(ReportGenerator master, int recordsPerPage) {

this.master = master;

this.recordsPerPage = recordsPerPage;

}

Setter injection : property tag This is achieved when the container invokes setter methods of a class to initialize the properties after invoking a default construct

Primitive:

bean id="reportService" class="com.infosys.demo.ReportService

property name="recordsPerPage" value="500" /

/bean


Non Primitive:

property name="master" ref="htmlReportGenerator" /

Setter Injection in Collections

public void setReports(List<ReportGenerator> reports) {

this.reports= reports;

}

config.xml

property name = "reports"

list

ref bean = "PDFReportGenerator /

ref bean = "HTMLReportGenerator /

/list

/property

  

Constructor Injection

Setter Injection

Dependency Injection is through parameterized constructor

Dependency Injection is through setter methods after invoking the default constructor

Need parameterized constructor in the POJO class

Need default constructor and setter methods in the POJO class

constructor-arg tag is used in configuration file

property tag is used in configuration file

constructor-arg tag "ref" attribute is used to provide dependency for Object type

property tag "ref" attribute is used to provide dependency for Object type

Preferred for

  • mandatory dependencies
  • Immutable dependencies
  • concise(pass several parameters once)

  • optional / changeable dependencies
  • Circular dependencies


Autowired: autowire ::: It is not required to specify all the properties values while defining bean in the configuration.
used for For non-primitive properties, and cannot be used to inject primitive and string values.

In XML configuration, autowire mode is specified in the bean definition using the autowire attribute.

Mode

Description

byName

  • Bean dependency is autowired based on the property name
  • If the matching bean does not exist in the container then bean will remain unwired
  • It internally uses setter injection

byType

  • Autowiring the bean dependency based on the property type
  • Properties for which there is no matching bean will remain unwired.
  • Spring throws an exception if there is more than one bean of the same type exists in the container
  • It internally uses setter injection

constructor

  • It is the same as autowiring byType but through constructor arguments.
  • Spring autowire the dependency based on constructor argument type through constructor injection.
  • Spring throws an exception if there is more than one bean of same type exists in the container

no

 Default mode which means no autowiring

  • no (no autowiring): it is same as without adding autowire

bean id="reportService" class="com.infosys.demo.ReportService" autowire="no"

property name="master" ref="htmlGenerator"/

property name="recordsPerPage" value="500"/

/bean

bean id="htmlReportGenerator"class="com.infosys.demo.HTMLReportGenerator" /

  • byName : bean id same as the property name

*bean id="reportService" class="com.infosys.demo.ReportService" autowire="byName"*

*property name="recordsPerPage" value="500" /*

*/bean*

*bean id="master" class="com.infosys.demo.PDFReportGenerator" /*

  • byType

*bean id="reportService" class="com.infosys.demo.ReportService" autowire="byType"*

*property name="recordsPerPage" value= "500"/*

*/bean*

*bean id="htmlReportGenerator" class="com.infosys.demo.HTMLReportGenerator" /*

  • constructor : mandatory to have parametarized constructor

*bean id="reportService" class="com.infosys.demo.ReportService" autowire="constructor"*

*constructor-arg name="recordsPerPage" value= "500"/*

*/bean*

*bean id="htmlReportGenerator" class="com.infosys.demo.HTMLReportGenerator" /*


Autowiring Mode

Description

byName

Autowiring based on bean name through setter injection

byType

Autowiring based on bean type through setter injection

constructor

Autowiring based on the bean type through parameterized constructor

no

No Autowiring, required dependency has to be injected explicitly using property or constructor-arg ref attribute in bean definition


Bean Scope (Scope tag)

A bean can be in singleton or prototype scope.

  • "singleton" scope is initialized during the container starts up and the same bean instance is provided for every bean request from the application.

bean id="reportService" class="com.infosys.demo.ReportService" scope="singleton"/

This is the default mode, if not specified explicitly in the bean definition

  • "prototype" scope, a new bean instance is created for every bean request from the application.

bean id="reportService" class="com.infosys.demo.ReportService" scope="prototype"/

 

Annotation based configuration

context:annotation-config in xml configuration, no need of property or constructor arg. but bean initilization is required.

@Autowired is by default wire the dependency based on type of bean == autowired byType


@Autowired On Property


@Autowired // For initializing only object dependency

private ReportGenerator master;

@Value("100") // Annotation for initializing primitive types

private int recordsPerPage;


@Autowired On Constructor


@Autowired

public ReportService(int recordsPerPage,ReportGenerator master) {

System.out.println("Parameterized Constructor");

this.recordsPerPage = recordsPerPage;

this.master = master;

}


@Autowired on Setter Method

@Autowired

public void setMaster(ReportGenerator master) {

System.out.println("Setter method of master property");

this.master = master;

}


It is generally advisable to autowire beans of workflow classes such as controller, service or repository and not advisable to autowire domain objects as they represent data in a table.


@Qualifier Annotation

How do we make @Autowired to work by name to allow the scenarios with more than one bean of same type in the configuration?


@Qualifier("beanId") annotation

@Autowired annotation wire the dependency based on type of bean and in byType there has to be only one bean of specified type in the configuraiton but in the specified scenario, there are two beans(htmlReportGenerator and pdfReportGenerator) of type ReportGenerator and hence there is an ambiguity on which bean to wire causing the application to throw an exception.

so the application is throwing UnsatisfiedDependencyException


@Autowired

@Qualifier("pdfReportGenerator")

private ReportGenerator master;


Analysis

@Autowired

@Qualifier("empRepo")

private EmployeeRepository employeeRepository;

bean id="employeeService" class="com.infosys.service.EmployeeService"/

bean id="employeeRepository" class="com.infosys.repo.EmployeeRepoImpl"/


Can you analyze the exception stack and say why application is throwing unSatisfiedDependencyException?


This is because, Spring failed to autowire EmployeeRepository bean in the service class as there is no bean in the container with name "empRepo". By default @Autowired is enabled to check the dependent bean and if the dependent bean does not exist then Spring throws unSatisfiedDependencyException exception and prevent the Spring container from launching successfully.

We can disable default behavior of @Autowired dependency check in certain scenarios to avoid run time exception even though the required bean does not exist in the container.

 

@Autowired(required=false)

@Qualifier("empRepo")

private EmployeeRepository employeeRepository;


Java based configuration

Introduction to Auto Scanning

Auto scanning helps to remove explicit bean definition using bean tag from the XML file.

  • Auto Scanning can be switched on by using context:component-scan.
  • context:component-scan can also do whatever context:annotation-config does in addition to auto scanning.

Use @Component annotation at POJO class level

context:component scan base package = "packageName"/

Spring scans specified "com.mypack" package and all its sub-packages to detect @Component annotated classes and create beans of these classes with default bean name same as the class name after making its first letter lowercase.


@Component: It indicates the class(POJO class) as a Spring component.

@Controller: It indicates Controller class(POJO class in Spring MVC) in the presentation layer.

@Repository: It indicates Repository class(POJO class in Spring DATA) in the persistence layer.

@Service: It indicates Service class(POJO class) in the business layer.

//default bean id "employeeRepositoryImpl" has to be used to access this bean

@Repository

public class EmployeeRepositoryImpl extends BaseRepository implements EmployeeRepository {

--------------

}

 

//default bean id "loanRepositoryImpl" has to be used to access this bean

@Repository

public class LoanRepositoryImpl extends BaseRepository implements LoanRepository {

-----------------

}

 

// Explicit bean id "employeeService" is specified and hence we should use "employeeService" to access the bean of this class

@Service("employeeService")

public class EmployeeServiceImpl implements EmployeeService {

-----------------------

}

 

// Explicit bean id "loanService" is specified

@Service("loanService")

public class LoanServiceImpl implements LoanService {

----------------------

}


Spring Java Based Configuration

We can eliminate the need for a XML file completely and provide the same configurations in a Java class file. Configurations in a XML file and the configurations in a Java class can co-exist as well.

@Configuration

    It indicates Spring container that the class contains the bean definitions.

    This is a pure Java approach to configure Spring container.

@Bean

    @Bean is used for defining a bean in Java based configuration.

In @Configuration annotated Java class, methods annotated with @Bean provides the bean definition.



  1. @Configuration indicates Spring that this class has bean definitions
  2. ReportService class bean definition. In this example, the bean id is "reportService" which is the default name (same as the method name)
  3. A class annotated with @Configuration is used as input for installing an ApplicationContext through AnnotationConfigApplicationContext class

  • Bean id is explicitly specified as "repoService", which overrides the default name
  • Bean scope is specified as "prototype"

@Configuration

public class AppConfig {

 

@Bean // htmlReportGenerator bean definition with bean definition

public ReportGenerator htmlReportGenerator(){

return new HTMLReportGenerator();

}

 

@Bean // pdfReportGenerator bean definition with bean definition

public ReportGenerator pdfReportGenerator(){

return new PDFReportGenerator();

}

 

@Bean // reportService bean definition with bean dependencies through constructor injection

public ReportService reportService1(){

ReportService reportService=new ReportService(pdfReportGenerator(), 150);

return reportService;

}

@Bean // reportService bean definition with bean dependencies through setter injection

public ReportService reportService2(){

ReportService reportService=new ReportService();

reportService.setMaster(htmlReportGenerator());

reportService.setRecordsPerPage("150");

return reportService;

}

 

 

public class EmployeeClient {

 

/** The ApplicationContext instantiation */

ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

 

-------------------------

}}


Java-based configuration support auto scan feature of Spring?
Yes, it supports auto scan feature of Spring using the annotation @ComponentScan.

@Configuration
@ComponentScan("com.infosys.demo")
public class AppConfig
{

}

 

Spring AOP

  • AOP (Aspect Oriented Programming) is used for applying common behaviors like transaction, security, logging etc. to the application.
  • These common behaviors generally needs to be called from multiple locations in an application. Hence, they are also called as cross cutting concerns in AOP.
Terminologies
  • In Spring AOP, we need to modularize and define each of the cross cutting concern in a single class called Aspect.
  • Each method of the Aspect which provides the implementation for the cross cutting concern is called an Advice.
  • The business methods of the program before or after which the advice can be called is known as a Joinpoint. The advice does not get inserted at every Joinpoint in the program. An advice gets applied only to the Joinpoints that satisfy the Pointcut defined for the advice.
  • Pointcut represents an expression that evaluates to the business method name before or after which the advice needs to be called.

Terminologies

Definition

Aspects

These are the cross-cutting concerns that cut across multiple classes. Example: Logging, transition, security, etc.

Join point

The possible program execution points where the Aspects are applied. In Spring it is always the method invocation

Advice

This represents code to be executed at the selected Joinpoint(s).

Pointcut

This identifies on what Joinpoints that advice needs to be applied. AspectJ Pointcut Expression Language(EL) is used for this identification

Target Object, AOP Proxy and Weaving

At runtime, proxies are created for the business objects(called target objects) with the Aspects linked using JDk Dynamic/CGLIB proxy. This process is called Weaving. The object created is called AOP Proxy.

Required jars

  • spring-aop-5.0.5.RELEASE.jar
  • aspectjweaver.jar (version 1.6.8 or later)

Enable AspectJ annotation support

XML based configuration: Include aop:aspectj-autoproxy/ tag in configuration file

Java Based Configuration: Annotate configuration class with @EnableAspectJAutoProxy

@AspectJ annotation

package mypack;

import org.aspectj.lang.annotation.Aspect;

@Aspect

public class LoggingAspect

{

        .....

        .....

}

Aspect class is a Java class with
  • Methods and fields
  • Pointcut declarations
  • Advice declarations

XML configuration

bean id="loggingAspect" class="mypack.LoggingAspect" /


}

Advice types

  • Before - Code specified with Before advice type is executed before a Joinpoint execution and then will continue with Joinpoint execution
  • AfterReturning - Code specified with AfterReturning advice type is executed after a Joinpoint executes and returns successfully without exceptions
  • AfterThrowing - Code specified with AfterThrowing is executed only when a Joinpoint exits by throwing exception
  • After - Similar to finally block in exception handling. Code specified with After advice type will be executed after the Joinpoint returns with or without exception
  • Around - Code specified with Around advice type has some logic which gets executed before Joinpoint invocation and some logic which gets executed after the Joinpoint returns successfully


  1. Joinpoint
  2. Joinpoint
  3. Defining beans
  4. "beforeAdvice" is invoked before the withdraw method execution and "afterAdvice" is invoked after the withdraw method execution
Enable auto Proxy

XML based configuration: Include aop:aspectj-autoproxy/ tag in configuration file
Java Based Configuration: Annotate configuration class with  @EnableAspectJAutoProxy

@Configuration
@EnableAspectJAutoProxy // To enable AspectJ annotation support for AOP implementation
@ComponentScan("com.infosys.demo") // To enable auto creation of aspect bean and other application beans
public class AppConfig {

}
  • After
// pointcut expression says that apply log advice to a generateReport() method
// which can take any number of arguments and can return any value, belongs to ReportService class from the package com.infosys.demo
@After("execution(* com.infosys.demo.ReportService.generateReport(..))")
  • before
// pointcut expression says that apply log advice to a generateReport() method
// which can take any number of arguments and can return any value, belongs to ReportService class from the package com.infosys.demo
@before("execution(* com.infosys.demo.ReportService.generateReport(..))")
  • After Returning
// Now the given advice gets applied only when generateReport() method executes successfully otherwise advice will not be applied.
@AfterReturning("execution(* com.infosys.demo.ReportService.generateReport(..))")
Access the return value
@AfterReturning(pointcut="execution(* com.infosys.service.EmployeeServiceImpl.createEmployee(..))" , returning="result")
public void logDetails(JoinPoint joinPoint,int result) { // JoinPoint must be the first in the list of arguments
//Log joinpoint signature details
System.out.println("Joinpoint Signature:"+ joinPoint.getSignature());
System.out.println(result)
  • AfterThrowing
@AfterThrowing(pointcut="execution(* com.infosys.demo.ReportService.generateReport(..))", throwing="ex")
public void logAfterAdvice(JoinPoint joinPoint, Exception ex){

System.out.println("After throwing Advice: " + ex.getMessage());

//Log Joinpoint signature details
System.out.println("Joinpoint signature :" + joinPoint.getSignature());

  • Around
@Around("execution(* com.infosys.demo.ReportService.generateReport(..))")
public Object logAdvice(ProceedingJoinPoint jp){
System.out.println("Before: In around advice");
long start = System.currentTimeMillis();
Object retVal = null;
try {
retVal = jp.proceed();

} catch (Throwable e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("After: In around advice");
System.out.println("Report generation took:" + (end-start)+ " milliseconds");
retVal = "Value returned from advice : " + retVal; // modifying the return value from Joinpoint
System.out.println(retVal);
return (retVal); // returning the modified value to client
}
}

Maven:
Maven is an Apache project, created with the main objective to make developer understand the state of total development effort in a short time.
  1. Maven is an intelligent, comprehensive, project management and build tool (developed in Java) to build deployable artifacts from the source code and has a superset of features available
  2. The core of Maven project is the POM file that is an XML file holding project configuration information. It contains meta data of/references to project resources like source code, test code, dependencies (external jar files) etc
  3. There will be a POM file with required dependency details located in the root directory of the Maven project.














Featured Post

HTML cheetsheet

List: Link tgs Dropdown

Popular Post

(C) Copyright 2018, All rights resrved InShortView. Template by colorlib