dispatcher-servlet.xml

 <mvc:resources location="/resources/" mapping="/resources/**"></mvc:resources>

HomeController.java

package com.mugil.controls;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class HomeController {	
	@RequestMapping("/home")	
	public String testMethod()
	{
		return "home";
	}
}

style.css

h1
{
  color : red;
}
  1. The Way aspect function calls are made are through proxy classes internally
  2. Internally the Spring framework creates proxy classed and calls to the code generated as per the xml are run in proxy class methods before the actual class are called
  3. In the below example in DrawingApp.java I try to create a object for the class circle by invoking factoryService getBean Method
  4. This method returns a Object of class ShapeServiceProxy with the custom methods for xml code added

ShapeService.java

package com.mugil.shapes;

public class ShapeService {
	private Circle objCircle;
	private Triangle objTriangle;
		
	public Circle getObjCircle() {
		return objCircle;
	}
	public void setObjCircle(Circle objCircle) {
		this.objCircle = objCircle;
	}
	public Triangle getObjTriangle() {
		return objTriangle;
	}
	public void setObjTriangle(Triangle objTriangle) {
		this.objTriangle = objTriangle;
	}	
}

ShapeServiceProxy.java

package com.mugil.shapes;

public class ShapeServiceProxy extends ShapeService {
	
	public Circle getObjCircle() {
		new LoggingAspect().getLogMessage();
		return super.getObjCircle();
	}
}

DrawingApp.java

package com.mugil.shapes;

public class DrawingApp
 {
	public static void main(String[] args) 
        {
		FactoryService objFactSer = new FactoryService();
		ShapeService objSS = (ShapeService)objFactSer.getBean("ShapeService");
		objSS.getObjCircle();
	}
}

FactoryService.java

package com.mugil.shapes;

public class FactoryService {
	
	public Object getBean(String className)
	{
		if(className.equals("Circle"))
			return new Circle();
		else if(className.equals("Triangle"))
			return new Triangle();
		else if(className.equals("DrawingApp"))
			return new DrawingApp();
		else if(className.equals("ShapeService"))
			return new ShapeServiceProxy();
			
		return null;
	}
}

spring.xml

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
	http://www.springframework.org/schema/aop 
	http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">

	<aop:aspectj-autoproxy />
        <bean id="customerBo" class="CustomerBoImpl" />
	<bean name="objTriangle" class="com.mugil.shapes.Triangle">
         	<property name="name" value="Triangle Name"></property>
        </bean>
        <bean name="objCircle" class="com.mugil.shapes.Circle">
    	        <property name="name" value="Circle Name"></property>
        </bean>
        <bean id="shapeService" class="com.mugil.shapes.ShapeService" autowire="byName"/>    	
        <bean name="loggingAspect" class="com.mugil.shapes.LoggingAspect"/>
          <aop:config>
    	     <aop:aspect id="loggingAspect" ref="loggingAspect">
    		<aop:pointcut expression="execution(* com.mugil.shapes.*.get*())" id="allGetters"/>
    		<aop:around method="LoggingAdvice2" pointcut-ref="allGetters"/>
    	     </aop:aspect>
          </aop:config>
</beans>

spring.xml

<aop:aspect id="loggingAspect" ref="loggingAspect">

equivalent to

@Aspect
public class LoggingAspect {

spring.xml

<aop:pointcut expression="execution(* com.mugil.shapes.*.get*())" id="allGetters"/>

equivalent to

@Pointcut("execution(* com.mugil.shapes.*.get*())")
public void allGetters()
{	 
}

spring.xml

<aop:around method="LoggingAdvice2" pointcut-ref="allGetters"/>

equivalent to

@Around("allGetters()")
public void LoggingAdvice2(ProceedingJoinPoint pjp)
{
.
.

<aop:pointcut expression="execution(* com.mugil.shapes.*.get*())" id="allGetters"/>
<aop:around method="LoggingAdvice2" pointcut-ref="allGetters"/>

could be replaced using pointCut

<aop:around method="LoggingAdvice2" pointcut="execution(* com.mugil.shapes.*.get*())"/>
Posted in AOP.

Loggable.java

package com.mugil.shapes;
public @interface Loggable {
}

.java

@Aspect
public class LoggingAspect 
{
@Around("@annotation(com.mugil.shapes.Loggable)")
	public void LoggingAdvice2(ProceedingJoinPoint pjp)
	{
		Object objObject = null;		
		
		try {
			System.out.println("Code before Method Execution Goes here");			
			objObject = pjp.proceed();
			System.out.println("Code after Method Execution Goes here");
		} catch (Throwable e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

Triangle.xml

public class Triangle 
{
   private String name;

   @Loggable
   public String getName() 
   {
     return name;
   }
.
.
}
Posted in AOP.

Aspect Oriented Programming answers cross-cutting concern.Cross-cutting concern is one 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.

Aspect – A module which has a set of APIs providing cross-cutting 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.

Advice – This is the actual action to be taken either before or after the method execution. This is actual piece of code that is invoked during program execution by Spring AOP framework.

LoggingAspect.java

package com.mugil.shapes;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class LoggingAspect 
{
	@Before("execution(public String getName())")
	public void loggingAdvice()
	{
		System.out.println("This is Logging Advice");
	}
}

DrawingApp.java

package com.mugil.shapes;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class DrawingApp 
{
	public static void main(String[] args) 
	{
		ApplicationContext objContext = new ClassPathXmlApplicationContext("Spring-Customer.xml");
		ShapeService  objCircle = (ShapeService) objContext.getBean("shapeService", ShapeService.class);
		System.out.println(objCircle.getObjCircle().getName());
System.out.println(objCircle.getObjTriangle().getName());
	}
}

Circle.java

package com.mugil.shapes;

public class Circle {
	private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

Triangle.java

package com.mugil.shapes;

public class Triangle {
	private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}	
}

Output

This is Logging Advice
Circle Name
This is Logging Advice
Triangle Name

@Before(“execution(public String getName())”)
Applies for all the methods with getName() signature (Triangle and Circle Class)

Output

This is Logging Advice
Circle Name
This is Logging Advice
Triangle Name

@Before(“execution(public String com.mugil.shapes.Circle.getName())”)
Applies for the methods with getName() signature (Circle Class)

Output

This is Logging Advice
Circle Name

@Before(“execution(public String com.mugil.shapes.*.getName())”)
Applies for getName() method in Triangle and Circle Class

Output

This is Logging Advice
Circle Name
This is Logging Advice
Triangle Name

@Before(“execution(public * get*())”)
Applies for all getters method in Triangle,Circle and ShapeService Class

Output

This is Logging Advice
This is Logging Advice
Circle Name
This is Logging Advice
This is Logging Advice
Triangle Name

@Before(“execution(public String getName(*))”)
Applies to all getName() method with one or more argument.

@Before(“execution(public String getName(..))”)
Applies to all getName() method with zero or more argument.

Pointcut – This is a set of one or more joinpoints where an advice should be executed. You can specify pointcuts using expressions or patterns as we will see in our AOP examples.

DrawingApp.java

package com.mugil.shapes;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class LoggingAspect 
{	
	@Before("allGetters()")
	public void loggingAdvice1()
	{
		System.out.println("This is Logging Advice 1");
	}
	
	@Before("allGetters()")
	public void loggingAdvice2()
	{
		System.out.println("This is Logging Advice 2");
	}
		
	@Pointcut("execution(* getName())")
	public void allGetters()
	{	
	}
}
  1. allGetters() method will be called when ever the getName() method of Circle (or) Triangle gets called
  2. Before allGetters() method gets called the loggingAdvice1() and loggingAdvice2() method gets called.

Output

This is Logging Advice 1
This is Logging Advice 2
Circle Name
 @Pointcut("execution(* com.mugil.shapes.*.get*(..))")

Applies for all the Getters within shapes package

 @Pointcut("execution(public * com.mugil.shapes.*.get*(..))")

Applies for all the Public Getters within shapes package

 @Pointcut("within(com.mugil.shapes.*)")

within applies for everything within class whereas execution applies only to the methods.

Runs for all methods getters and setters in com.mugil.shapes.* package.

@Pointcut("args(..)")

Runs for all methods getters and setters.

Join point – This represents a point in your application where you can plug-in AOP aspect. You can also say, it is the actual place in the application where an action will be taken using Spring AOP framework.

Using JoinPoint we can have access to the Object in the advice method.

LoggingAspect.java

package com.mugil.shapes;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class LoggingAspect {
	
	@Before("allGetters()")
	 public void LogginAdvice(JoinPoint joinpoint)
    {
		System.out.println("advice is run");
	    System.out.println(joinpoint.toString());
    }
	
	@Before("args(name)")
	public void LoggingAdvice2(String name)
	{
		System.out.println("-- " + name);
	}
	
	@Pointcut("execution(* com.mugil.shapes.*.get*())")
	public void allGetters()
	{	
	}
}

DrawingApp.java

public class DrawingApp {
	public static void main(String[] args) {
		ApplicationContext objContext = new ClassPathXmlApplicationContext("Spring-Customer.xml");
		ShapeService  objCircle = (ShapeService) objContext.getBean("shapeService", ShapeService.class);
objCircle.getObjTriangle().setName("Test Tri");
		System.out.println(objCircle.getObjTriangle().getName());	
	}
}

Output

advice is run
execution(Triangle com.mugil.shapes.ShapeService.getObjTriangle())
-- Test Tri
advice is run
execution(Triangle com.mugil.shapes.ShapeService.getObjTriangle())
advice is run
execution(String com.mugil.shapes.Triangle.getName())
Test Tri

LoggingAspect.java

@Aspect
public class LoggingAspect {
	
	@Before("allGetters()")
	 public void LogginAdvice(JoinPoint joinpoint)
    {
		System.out.println("advice is run");
	    System.out.println(joinpoint.toString());
    }
	
	@AfterReturning(pointcut ="args(name)", returning="returnString")
	public void LoggingAdvice2(String name, String returnString)
	{
		System.out.println("This is Input to Method " + name);
		System.out.println("This is Returned  from  Method " + returnString);
	}
	
	@AfterThrowing(pointcut="args(name)", throwing="ex")
	public void LoggingAdvice4(String name, RuntimeException ex)
	{
		System.out.println("This will be Printed incase of Exception is Thrown in Method");		
		System.out.println(ex);
	}

	
	@Pointcut("execution(* com.mugil.shapes.*.get*())")
	public void allGetters()
	{	
	}
}

Using Around

@Around("allGetters()")
	public void LoggingAdvice2(ProceedingJoinPoint pjp)
	{
		Object objObject = null;		
		
		try {
			System.out.println("Code before Method Execution Goes here");			
			objObject = pjp.proceed();
			System.out.println("Code after Method Execution Goes here");
		} catch (Throwable e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
Posted in AOP.

Event Handling requires 3 Things

  1. Event Publisher
  2. Event Listener
  3. Event

CustomEvent.java(Event)

import org.springframework.context.ApplicationEvent;

public class CustomEvent extends ApplicationEvent
{
	public CustomEvent(Object source) 
        {
		super(source);
	}	

	public String toString()
	{
		return "Custom Message from Custom Event";
	}
}

CustomEventListener.java(Event Listener)

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

@Component
public class CustomEventListener implements ApplicationListener
{
	@Override
	public void onApplicationEvent(ApplicationEvent event) {		
		System.out.println(event.toString());
	}
}

Circle.java(Event Publisher)

import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;

@Component
public class Circle implements Shape, ApplicationEventPublisherAware
{			
	private ApplicationEventPublisher publisher;
	
	@Override
	public void drawShape() {	
		CustomEvent objCustEvent = new CustomEvent(this); 
		publisher.publishEvent(objCustEvent);
	}
	
	@Override
	public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
		this.publisher = publisher;
	}

	public ApplicationEventPublisher getPublisher() {
		return publisher;
	}

	public void setPublisher(ApplicationEventPublisher publisher) {
		this.publisher = publisher;
	}	
}	

Java Specification Request JSR 250

spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
		http://www.springframework.org/schema/context 
		http://www.springframework.org/schema/context/spring-context-2.5.xsd">	
	<bean id="pointC" class="com.mugil.shapes.Point">
		<property name="x" value="20"/>
		<property name="y" value="0"/>
	</bean> 	
	<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="location" value="constant.properties"></property>
	</bean>	
	<bean class="com.mugil.shapes.Circle" id="circleId">
	</bean>	
	<context:annotation-config/>
</beans>

circle.java

public class Circle implements Shape{		
	private Point center;
	
	@Override
	public void drawShape() {
		System.out.println("Shape of Circle ");
		System.out.println("Center of Cirlce "+ getCenter().getX() + " - " + getCenter().getY());
	}

	public Point getCenter() {
		return center;
	}

	@Resource(name="pointC")
	public void setCenter(Point center) {
		this.center = center;
	}
	
	@PostConstruct
	public void initilizeMe() 
	{
		System.out.println("Initialized");
	}
	
	@PreDestroy
	public void destroyMe() 
	{
		System.out.println("Derstroyed");
	}
}

If name is not specified after the @Resource it will look for same name matching bean in the spring.xml file.

@PostConstruct and @PreDestroy will be called when circle bean is initialized and destroyed

Defining Bean using Annotations
spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
		http://www.springframework.org/schema/context 
		http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:component-scan base-package="com.mugil.shapes"/>
</beans>

circle.java

@Component
public class Circle implements Shape
{	
.
.
}

drawingApp.java

public class DrawingApp {
	public static void main(String[] args)  {
		 AbstractApplicationContext objContext = new ClassPathXmlApplicationContext("spring1.xml");
		 objContext.registerShutdownHook();
		Shape objShape =  (Shape)objContext.getBean("circle");
.
.
}

Using MessageSource
spring.xml

<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
		<property name="basenames">
			<list>
				<value>constant</value>
			</list>
		</property>
	</bean>

constant.properties

TestMessage=Mugil

DrawingApp.java

 AbstractApplicationContext objContext = new ClassPathXmlApplicationContext("spring1.xml");
System.out.println(objContext.getMessage("TestMessage", null, "Default Message", null));

Output

 Mugil

Using instance of Message Source in Bean Class
spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
		http://www.springframework.org/schema/context 
		http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
		<property name="basenames">
			<list>
				<value>constant</value>
			</list>
		</property>
	</bean>
	<context:annotation-config/>
	<context:component-scan base-package="com.mugil.shapes"/>
</beans>

circle.java

@Component
public class Circle implements Shape{		
	private Point center;
	
	@Autowired
	private MessageSource messageSource;	
	
	@Override
	public void drawShape() {
		System.out.println("Shape of Circle ");		
		System.out.println(this.messageSource.getMessage("TestMessage", null, "Vannan", null));
	}

	public Point getCenter() {
		return center;
	}

	@Resource(name="pointC")
	public void setCenter(Point center) {
		this.center = center;
	}
	
	public MessageSource getMessageSource() {
		return messageSource;
	}

	public void setMessageSource(MessageSource messageSource) {
		this.messageSource = messageSource;
	}
	
}

this.messageSource.getMessage(“TestMessage”, null, “Vannan”, null)

Variable substitution in Message Source

circle.java

@Component
public class Circle implements Shape{		
	private Point center;
	
	@Autowired
	private MessageSource messageSource;
	
	
	@Override
	public void drawShape() {
		System.out.println("Center of Cirlce");		System.out.println(this.messageSource.getMessage("TestMessage2", new Object[]{center.getX(), center.getY()}, "Vannan", null));
	}
.
.
.
}

this.messageSource.getMessage(“TestMessage2”, new Object[]{center.getX(), center.getY()}, “Vannan”, null)

constant.properties

TestMessage=Mugil
TestMessage2=Center of Circle : ({0}, {1})

@Required
Incase the bean value is not defined using required will display the spring error message instead of null pointer exception for the bean whose value is not defined.

spring.xml

<bean class="com.mugil.shapes.Circle" id="circleId">		
</bean>

Note above the pointA is undefined for above circle bean

Spring Error without @Required annotation

Exception in thread "main" java.lang.NullPointerException
	at com.mugil.shapes.Circle.drawShape(Circle.java:11)
	at com.mugil.shapes.DrawingApp.main(DrawingApp.java:17)

circle.java

public class Circle implements Shape{
	private Point center;
	
	@Override
	public void drawShape() {
		System.out.println("Shape of Circle ");
		System.out.println("Center of Cirlce "+ getCenter().getX() + " - " + getCenter().getY());
	}

	public Point getCenter() {
		return center;
	}

	@Required
	public void setCenter(Point center) {
		this.center = center;
	}		
}

spring.xml

<bean class="com.mugil.shapes.Circle" id="circleId">		
</bean>
	
<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/>

Spring Error is Thrown

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'circleId' defined in class path resource [spring1.xml]: Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanInitializationException: Property 'center' is required for bean 'circleId'

Autowired Annotation

  1. @Autowired works by taking into consideration type,name,qualifier
  2. If type not found name will be considered

spring.xml(by Type)

<beans>
	<bean id="PointA" class="com.mugil.shapes.Point">
		<property name="x" value="0"/>
		<property name="y" value="20"/>
	</bean>	
	<bean class="com.mugil.shapes.Circle" id="circleId"></bean>	
	<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
</beans>

spring.xml(by Name)

<beans>
	<bean id="center" class="com.mugil.shapes.Point">
		<property name="x" value="0"/>
		<property name="y" value="20"/>
	</bean>	
	<bean class="com.mugil.shapes.Circle" id="circleId"></bean>	
	<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
</beans>

In above xml center is the name of instance variable in circle class
spring.xml(by Qualifier)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
		http://www.springframework.org/schema/context 
		http://www.springframework.org/schema/context/spring-context-2.5.xsd">		
	<bean id="pointA" class="com.mugil.shapes.Point">
		<qualifier value="circle"/>			
		<property name="x" value="20"/>
		<property name="y" value="0"/>
	</bean>	
	<bean class="com.mugil.shapes.Circle" id="circleId"></bean>	
	<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
</beans>

circle.java

public class Circle implements Shape{
	@Autowired
	@Qualifier("circle")
	private Point center;
	
	@Override
	public void drawShape() {
		System.out.println("Shape of Circle ");
		System.out.println("Center of Cirlce "+ getCenter().getX() + " - " + getCenter().getY());
	}

	public Point getCenter() {
		return center;
	}
	
	public void setCenter(Point center) {
		this.center = center;
	}		
}

Reading constant from properties file
constant.properties

PointA.PointX=-20
PointA.PointY=0

spring.xml

<beans>
	<bean id="pointA" class="com.mugil.shapes.Point">
		<property name="x" value="${PointA.PointX}"/>
		<property name="y" value="${PointA.PointY}"/>
	</bean>
	<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="location" value="constant.properties"></property>
	</bean>
</beans>

Using Interface
spring.xml

<beans>
	<bean id="pointA" class="com.mugil.shapes.Point">
		<property name="x" value="${PointA.PointX}"/>
		<property name="y" value="${PointA.PointY}"/>
	</bean>
	<bean class="com.mugil.shapes.Circle" id="circleId">
		<property name="center" ref="pointA"/>
	</bean>
</beans>

shape.java

public interface Shape { 
	public void drawShape();
}

triangle.java

public class Triangle implements Shape
{
 public void drawShape()
 {
   System.out.println("Shape of Triangle");
 }
}

circle.java

public class Circle implements Shape{
	private Point center;
	
	@Override
	public void drawShape() {
		System.out.println("Shape of Circle ");
		System.out.println("Center of Cirlce "+ getCenter().getX() + " - " + getCenter().getY());
	}

	public Point getCenter() {
		return center;
	}

	public void setCenter(Point center) {
		this.center = center;
	}		
}

The objShape will call the draw method based on the instance referenced at runtime
shape.java

public class DrawingApp {
	public static void main(String[] args)  {
		 ApplicationContext objContext = new ClassPathXmlApplicationContext("spring1.xml");
		Shape objShape =  (Shape)objContext.getBean("circleId");
		objShape.drawShape();
	}
}

ApplicationContextAware and BeanNameAware

  1. The Aware interface has the feel of the listener, callback, or observer design patterns.
  2. Aware interface, which is a super interface to the two.The xxxAware interface is a common pattern used within the Spring framework.
  3. They are typically used to allow a Spring managed bean to be given an object (via the interfaces setXxx method) at Spring bootstrap time.During bootstrapping, Spring will examine each bean to determine if it implements any of the xxxAware interfaces. When one is found, it invokes the interface method, providing the piece of information that is being asked for.

In Spring Bean Lifecycle from creation to Destruction is managed by Spring Container. There may be scenarios where we would want to access bean created by spring container from non spring managed class. The beans created by spring container is available in ApplicationContext. Whenever there are any changes to the bean it would be updated in applicationcontext.
By implementing ApplicationContextAware in the bean which should be accessed outside and calling the setApplicationContext when new ClassPathXmlApplicationContext is called from outside class we can have access to bean from context.

SpringBeans.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-3.0.xsd">
	<bean id="helloBean" class="com.mkyong.core.HelloWorld">
		<property name="name" value="Mugil" />
	</bean>
</beans>

HelloWorld.java – Spring Bean

public class HelloWorld implements ApplicationContextAware
{
 private String name;
 private ApplicationContext objContext = null;


 public void setName(String name) {
  this.name = name;
 }

 public void printHello() {
  System.out.println("Spring 3 : Hello ! " + name);
 }

 public void setApplicationContext(ApplicationContext arg0) throws BeansException {
  this.objContext = arg0;
  System.out.println("Called when Object to new ClassPathXmlApplicationContext('springbeans.xml') is created");
 }
}

App.java

public class App 
{
 public static void main(String[] args) 
 {
  ApplicationContext context = new ClassPathXmlApplicationContext("SpringBeans.xml");

  HelloWorld obj = (HelloWorld) context.getBean("helloBean");
  obj.printHello();
 }
}

Output

Called when Object to new ClassPathXmlApplicationContext('springbeans.xml') is created
Spring 3 : Hello ! Mugil

When spring instantiates beans, it looks for a couple of interfaces like ApplicationContextAware and InitializingBean. If they are found, the methods are invoked.

Class<?> beanClass = beanDefinition.getClass();
Object bean = beanClass.newInstance();
if (bean instanceof ApplicationContextAware) 
{
    ((ApplicationContextAware) bean).setApplicationContext(ctx);
}

In newer version it may be better to use annotations, rather than implementing spring-specific interfaces

@Inject // or @Autowired
private ApplicationContext ctx

When BeanPostProcessor implement Object to execute the postProcessBeforeInitialization method,for example ApplicationContextAwareProcessor that added before.

private void invokeAwareInterfaces(Object bean) {
        if (bean instanceof Aware) {
            if (bean instanceof EnvironmentAware) {
                ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
            }
            if (bean instanceof EmbeddedValueResolverAware) {
                ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(
                        new EmbeddedValueResolver(this.applicationContext.getBeanFactory()));
            }
            if (bean instanceof ResourceLoaderAware) {
                ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
            }
            if (bean instanceof ApplicationEventPublisherAware) {
                ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
            }
            if (bean instanceof MessageSourceAware) {
                ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
            }
            if (bean instanceof ApplicationContextAware) {
                ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
            }
        }
    }

When it is Invoked
Shape.java

//Application System out would be Printed
ApplicationContext objContext = new ClassPathXmlApplicationContext("spring1.xml");

//this.strTriangle would be printed
BeanFactory  objBeanFactory = new XmlBeanFactory(new FileSystemResource("spring.xml"));
Triangle objTriangle2 =  (Triangle)objBeanFactory.getBean("triangleName");

BeanFactoryAware
BeanFactory is used for BeanFactoryAware whereas ApplicationContextAware is used for ApplicationContext.Note that the ApplicationContext interface is a subclass of BeanFactory, and provides additional methods on top of the basic BeanFactory interface.

BeanNameAware Interface
Bean implementing this interface can get its name defined in the Spring container
One possible area of use could be if your building on/ extending the spring framework and would like to acquire the bean name for logging purposes/wiring them etc.

MyBeanName.java

public class MyBeanName implements BeanNameAware 
{
 @Override
 public void setBeanName(String beanName) 
 {
  System.out.println(beanName);
 }
}

Config.java

@Configuration
public class Config 
{ 
    @Bean(name = "myCustomBeanName")
    public MyBeanName getMyBeanName() {
        return new MyBeanName();
    }
}
myCustomBeanName
  1. beanName property represents the bean id registered in the Spring container.When a new bean is given a name in the spring container and if you want to access the name then BeanNameAware should be used
  2. In the above example when the code is run it outputs myCustomBeanName which is the name offered to bean by container at runtime.
  3. If no name is given its going to print name of the method – getMyBeanName as bean name

If you require access to the additional features available on an ApplicationContext? If so, then you should of course use ApplicationContextAware. If not, BeanFactoryAware will be sufficient.Amongst many other things, an ApplicationContext has additional methods for inspecting the beans e.g. containsBeanDefinition, getBeanDefinitionCount, getBeanDefinitionNames, getBeanNamesForType, getBeansOfType that may be useful to you and which are not available on BeanFactory

we should avoid using any of the Aware interfaces, unless we need them. Implementing these interfaces will couple the code to the Spring framework.

————————————————————————————————————————————————————

Inheriting Bean Definition
spring.xml

<beans>
	<bean id="parentTriangle" class="com.mugil.shapes.Triangle">
		<property name="pointA">
			<ref bean="pointA"/>
		</property>
	</bean>
	<bean id="triangleId" class="com.mugil.shapes.Triangle" parent="parentTriangle">
		<property name="pointB" ref="pointB"/>
		<property name="pointC" ref="pointC"/>
	</bean>
<beans>

Above the bean parentTriangle is inherited by the child bean triangleId

spring.xml
Bean definition can also be made as abstract by using abstract=”true” like one below

<beans>
	<bean id="parentTriangle" class="com.mugil.shapes.Triangle" abstract="true">
		<property name="pointA">
			<ref bean="pointA"/>
		</property>
	</bean>
</beans>

Managing Lifecycle of Bean

  1. Note the object for Context objContext is referred using AbstractApplicationContext not ApplicationContext
  2. registerShutdownHook() registers a hook which gets called at the end of application for cleanup

Shape.java

 AbstractApplicationContext objContext = new ClassPathXmlApplicationContext("spring1.xml");
 objContext.registerShutdownHook();

Triangle.java

public class Triangle implements InitializingBean, DisposableBean 
{
 @Override
 public void destroy() throws Exception {
   System.out.println("DisposableBean Called");
 }

 @Override
 public void afterPropertiesSet() throws Exception {
   System.out.println("InitializingBean Called");
 }
}

We can all initialize the methods which should be called for initialization in spring.xml as below
spring.xml

<bean id="triangleId" class="com.mugil.shapes.Triangle" init-method="myInit" destroy-method="myDestroy">
                <property name="pointA" ref="pointA"/>
		<property name="pointB" ref="pointB"/>
		<property name="pointC" ref="pointC"/>
	</bean>

Triangle.java

public class Triangle implements InitializingBean, DisposableBean 
{
  public void myInit()
  {
    System.out.println("Custom Init Method");
  }
	
  public void myDestroy()
  {
    System.out.println("Custom Destroy Method");
  }
}

Priority of method call when it is defined by using XML and Interface implementation

  1. Init method of XML will be called
  2. Custom Init method of Interface will be called
  3. Destroy method of XML will be called
  4. Custom Destroy method of Interface will be called

Bean Post Processor

  1. Will work before and after bean initialization
  2. Works only when called using application initialization of bean. Does not work with setter initialization
  3. called for every initialization of parent and child bean in class

Bean Post Processor

<beans>
	<bean id="triangleId" class="com.mugil.shapes.Triangle">
	    <property name="pointA" ref="pointA"/>
		<property name="pointB" ref="pointB"/>
		<property name="pointC" ref="pointC"/>
	</bean>
	
	<bean id="pointA" class="com.mugil.shapes.Point">
		<property name="x" value="-20"/>
		<property name="y" value="0"/>
	</bean>
	<bean id="pointB" class="com.mugil.shapes.Point">
		<property name="x" value="0"/>
		<property name="y" value="0"/>
	</bean>
	<bean id="pointC" class="com.mugil.shapes.Point">
		<property name="x" value="20"/>
		<property name="y" value="0"/>
	</bean>
	
	<bean class="com.mugil.shapes.BeanInitialization"/>
	
</beans>

BeanInitialization.java

public class BeanInitialization implements BeanPostProcessor
{
	@Override
	public Object postProcessAfterInitialization(Object obj, String objName) throws BeansException 
       {
	  System.out.println("After Initialization of " + objName);
	  return obj;
	}

	@Override
	public Object postProcessBeforeInitialization(Object obj, String objName) throws BeansException 
       {
	  System.out.println("Before Initialization of " + objName);
	  return obj;
	}

}

So the above code runs four times for bean initialization of pointA,pointB,pointC and Triangle

shape.java

public class Shape 
{ 
  public static void main(String[] args)  
  {
    ApplicationContext objContext = new ClassPathXmlApplicationContext("spring1.xml");
    Triangle objTriangle2 =  (Triangle)objContext.getBean("triangleId");
    . 
    .
    .
}

BeanFactoryPostProcessor initialization happens before the beans gets initialized in the bean factory.

BeanInitialization2.java

public class BeanInitialization2 implements BeanFactoryPostProcessor
{
  @Override
  public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0) throws BeansException 
  {
     System.out.println("This is Bean factory Post Processor");
  }
}

spring.xml

<beans>
  <bean class="com.mugil.shapes.BeanInitialization2"/>	
</beans>