I am getting familiar with Spring. Strangely code below invokes constructor twice whereas I expected it to be called once. Can someone help?
package com.tutorialspoint;
import java.util.List;
import org.springframework.context.event.ContextStartedEvent;
import org.springframework.context.ApplicationListener;
public class DemoClass implements ApplicationListener<ContextStartedEvent> {
private String message;
private int nrOfMessages;
public DemoClass(String mes, int nr) {
message = mes;
nrOfMessages = nr;
System.out.println("Demo class constructor. Parameters: " + mes + " " + nr);
}
// a setter method to set List
public void setNrOfMessages(int nr) {
this.nrOfMessages = nr;
}
// Message setter
public void setMessage(String message) {
this.message = message;
}
// prints and returns all the elements of the list.
public void dumpContents() {
System.out.println("Message: " + message + " Nr of messages: " + nrOfMessages);
}
public void onApplicationEvent(ContextStartedEvent event) {
System.out.println("ContextStartedEvent Received");
}
}
The bean and main:
package com.tutorialspoint;
import java.io.FileNotFoundException;
import java.util.List;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
public class MainApp {
public static void main(String[] args) {
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
context.start();
// Create an object
DemoClass obj = (DemoClass) context.getBean("democlassBean");
// Dump contents
obj.dumpContents();
}
}
bean
<?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-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean id="democlassBean" class="com.tutorialspoint.DemoClass"
scope="prototype">
<constructor-arg value="Hello world beans."/>
<constructor-arg value="300"/>
</bean>
<bean class="com.tutorialspoint.InitHelloWorld"></bean>
</beans>
This is the output:
Demo class constructor. Parameters: Hello world beans. 300
BeforeInitialization : democlassBean
AfterInitialization : democlassBean
ContextStartedEvent Received
Demo class constructor. Parameters: Hello world beans. 300
BeforeInitialization : democlassBean
AfterInitialization : democlassBean
Message: Hello world beans. Nr of messages: 300
You can see constructor is being called twice - why???
Here is also code for initHelloWorld:
package com.tutorialspoint;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.BeansException;
public class InitHelloWorld implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeforeInitialization : " + beanName);
return bean; // you can return any other object as well
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("AfterInitialization : " + beanName);
return bean; // you can return any other object as well
}
}
It seems, it is not good idea to have prototype bean to act as ApplicationListener.
Check http://forum.spring.io/forum/spring-projects/container/35965-applicationlistener-interface-makes-beans-eagerly-instantiated
for details.
You can make it work, but with some exta steps are required (described in lined post). Note that linked post is somewhat old (year 2007) and it is likely that some of the implementation details covered there are not valid anymore.
If you really care about number of instances being created- what about creating two classes- one as prototype, and another (singlelton) that acts as ApplicationListener?
Related
I'm learning the bean AOP with Annotation and xml config but Spring does not create the beans.
Interface
package com.spring.studying.SpringAop.FrameworkService.AspectJAnnotation;
public interface Artist {
void perform();
}
Guitar Class
package com.spring.studying.SpringAop.FrameworkService.AspectJAnnotation;
import org.springframework.stereotype.Component;
#Component("grammyGuitarist")
public class GrammyGuitarist implements Artist{
#Override
public void perform() {
System.out.println("Start to play guitar");
}
public void playGuitar(String brand)
{
System.out.println("Get Guitar "+brand);
}
public void rest()
{
System.out.println("zzZZ!!!!");
}
}
Documentarist
package com.spring.studying.SpringAop.FrameworkService.AspectJAnnotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
#Component(value="documentaries")
public class Documentarist {
private GrammyGuitarist guitarist;
public void executed()
{
guitarist.playGuitar("LakeWood");
guitarist.perform();
guitarist.rest();
}
#Autowired
public void setGuitarist(GrammyGuitarist guitarist) {
this.guitarist = guitarist;
}
}
Advice Class
package com.spring.studying.SpringAop.FrameworkService.AspectJAnnotation;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
#Component("annotatedAdvice")
#Aspect
public class AnnotatedAdvice {
#Pointcut("execution(* rest*(..)) && args(brand)")
public void restExecution(String brand)
{
}
#Pointcut("bean(grammyGuitarist)")
public void isGrammyGuitarist()
{
}
#Before("restExecution(brand) && isGrammyGuitarist")
public void simpleBeforeAdvice(JoinPoint joinPoint , String brand)
{
System.out.println("Before Advice processing");
System.out.println("Playing guitar :" + brand);
System.out.println("Executing :"+ joinPoint.getSignature().getDeclaringTypeName() +" "+joinPoint.getSignature().getName());
}
}
Demo Class
package com.spring.studying.SpringAop.FrameworkService.AspectJAnnotation;
import org.springframework.context.support.GenericXmlApplicationContext;
import java.util.Arrays;
public class AspectJAnnotationDemo {
public static void main(String[] args) {
GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
ctx.load("aop-aspectj-annotation-style.xml");
ctx.refresh();
Arrays.stream(ctx.getBeanDefinitionNames()).forEach(System.out::println);
Documentarist documentarist = ctx.getBean("documentaries",Documentarist.class);
documentarist.executed();
}
}
My Xml Config File
<?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"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
">
<context:annotation-config/>
<context:component-scan base-package="com.spring.studying.SpringAop"/>
<aop:aspectj-autoproxy/>
</beans>
None of my beans were created just 6 default beans from spring.
I have try to create bean with tag and it worked fine . Just don't know why my code did not work with the annotation.
restExecution #Pointcut is wrong, because rest method of GrammyGuitarist doesn't take any arguments. playGuitar method takes brand argument, so you need to change your pointcut a bit:
#Component("annotatedAdvice")
#Aspect
public class AnnotatedAdvice {
#Pointcut("execution(* play*(..)) && args(brand)")
public void playExecution(String brand) {
}
#Pointcut("bean(grammyGuitarist)")
public void isGrammyGuitarist() {
}
#Before("playExecution(brand) && isGrammyGuitarist()")
public void simpleBeforeAdvice(JoinPoint joinPoint, String brand) {
System.out.println("Before Advice processing");
System.out.println("Playing guitar :" + brand);
System.out.println("Executing :" + joinPoint.getSignature().getDeclaringTypeName() + " " + joinPoint.getSignature().getName());
}
}
When you do this, aspects will indeed be created, but you will start getting exceptions:
Bean named 'grammyGuitarist' is expected to be of type 'com.example.demo.aspect.GrammyGuitarist' but was actually of type 'jdk.proxy2.$Proxy14'
This is because GrammyGuitarist implements an interface, and in this case Spring AOP uses JDK dynamic proxies
The simplest solution would be to force the use of a CGLIB proxy. To do this, you need to add an annotation above the aspect:
#EnableAspectJAutoProxy(proxyTargetClass = true)
After that, the program will give the expected result:
annotatedAdvice
documentaries
grammyGuitarist
org.springframework.aop.config.internalAutoProxyCreator
Before Advice processing
Playing guitar :LakeWood
Executing :com.example.demo.aspect.GrammyGuitarist playGuitar
Get Guitar LakeWood
Start to play guitar
zzZZ!!!!
In Spring Boot, CGLIB enforcement is enabled by default. Check this question for better understanding
I'm learning Springs with annotations and auto wiring. I tried three types of auto wiring
Constructor
Setter injection
Method
This is my configuration
<?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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- add entry for component scanning -->
<context:component-scan base-package="com.aht.spring.entity"></context:component-scan>
</beans>
These are my entities
Coach.java
package com.aht.spring.entity.coach;
public interface Coach {
String getDailyWorkOut();
String getDailyFortune();
}
FortuneService
package com.aht.spring.entity.fortune;
public interface FortuneService {
String getFortune();
}
HappyFortuneService
package com.aht.spring.entity.fortune;
import org.springframework.stereotype.Component;
#Component
public class HappyFortuneService implements FortuneService {
public String getFortune() {
return "Feel energetic for first half of trainning";
}
}
FootBallCoach
package com.aht.spring.entity.coach;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.aht.spring.entity.fortune.FortuneService;
#Component
public class FootBallCoach implements Coach {
private FortuneService fortuneService;
#Autowired
public FootBallCoach(FortuneService fortuneService) {
this.fortuneService = fortuneService;
}
public String getDailyWorkOut() {
return "Practice one-on-one for 2 hours";
}
public String getDailyFortune() {
return fortuneService.getFortune();
}
}
CricketCoach
package com.aht.spring.entity.coach;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.aht.spring.entity.fortune.FortuneService;
#Component
public class CricketCoach implements Coach {
private FortuneService fortuneService;
public CricketCoach() {
System.out.println("Default constructor");
}
#Autowired
public void setFortuneService(FortuneService fortuneService) {
this.fortuneService = fortuneService;
}
public String getDailyWorkOut() {
return "Practice out field tips";
}
public String getDailyFortune() {
return fortuneService.getFortune();
}
}
BaseBallCoach
package com.aht.spring.entity.coach;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.aht.spring.entity.fortune.FortuneService;
#Component
public class BaseBallCoach implements Coach {
private FortuneService fortuneService;
public String getDailyWorkOut() {
return "Practice curve whole day";
}
public String getDailyFortune() {
return fortuneService.getFortune();
}
#Autowired
public void customAutoWire(FortuneService fortuneService) {
this.fortuneService = fortuneService;
}
}
I've three classes for executing three ways of auto wiring, Constructor and Setter worked fine, but when method wise auto wiring was done a wrong constructor was called. One thing I missed in my in my BaseBallCoach class was a default constructor, but anyhow compiler will automatically generate one for me right?
This is my CoachMethodInjectionApp.java where I executed method auto wiring
package com.aht.spring.app;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.aht.spring.entity.coach.Coach;
public class CoachMethodInjectionApp {
public static void main(String[] args) {
// read config-file
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// get beans
Coach coach = context.getBean("baseBallCoach", Coach.class);
// get dependencies
System.out.println(coach.getDailyFortune());
// get daily workout
System.out.println(coach.getDailyWorkOut());
// close context
context.close();
}
}
This was the output
Default constructor
Feel energetic for first half of trainning
Practice curve whole day
First line of output is what I don't understand Default constructor, why the constructor of CricketCoach executing??
As CricketCoach class is annotated with #Component and the package is scanned when the Spring container starts it will create an instance of type CricketCoach by calling the no-arg constructor
All the beans defined in the xml file or annotated with #Component or any extension of #Component from scanned packages will be created at start time of the spring container no matter if they will be used or not
You're creating a new instance of Coach class here:
Coach coach = context.getBean("baseBallCoach", Coach.class);
Everytime new instance is created it is executing a constructor. In which you have call to System.out.println("Default constructor");. You may try removing #Component from Cricket Coach imlpementation.
i am trying to run a Spring AOP demo program using Spring Advice parameters. I am getting exception "java.lang.IllegalArgumentException: error at ::0 formal unbound in pointcut" while executing the below code. Please help me to understand what is wrong with the below code.
Performance.java
package com.aop.annotations.example4;
public interface Performance {
public void perform(int performanceNum, String performanceName) throws Exception;
public void buyTicket(int price) throws Exception;
}
CircusPerformance.java
package com.aop.annotations.example4;
public class CircusPerformance implements Performance {
#Override
public void perform(int performanceNum, String performanceName) throws Exception {
System.out.println("Circus Performance number:"+performanceNum+" and Performance name :"+performanceName+" in progress..");
}
#Override
public void buyTicket(int price){
System.out.println("Buy Ticket for Circus performance");
}
}
DancePerformance.java
package com.aop.annotations.example4;
public class DancePerformance implements Performance{
#Override
public void perform(int performanceNum, String performanceName) throws Exception {
System.out.println("Dance Performance number:"+performanceNum+" and Performance name :"+performanceName+" in progress..");
}
#Override
public void buyTicket(int price) throws Exception {
System.out.println("Buy Ticket for Dance performance");
}
}
Audience.java
package com.aop.annotations.example4;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
#Aspect
#Component
public class Audience {
#Pointcut("execution(* com.aop.annotations.example4.Performance.*(..)) && args(int,String)")
public void performance() {
}
#Pointcut("execution(* com.aop.annotations.example4.Performance.*(..)) && args(int)")
public void buyTicket() {
}
#After("buyTicket()")
public void afterTicket(JoinPoint jp, int price) {
System.out.println("Start of method: " + jp.getSignature().getName() + " of Class: "
+ jp.getTarget().getClass().getSimpleName());
System.out.println("Buying Ticket of Price :" + price);
System.out.println("Silencing cell phones");
System.out.println("Taking seats");
}
#Before("performance()")
public void beforePerformance(JoinPoint jp, int performanceNum, String performanceName) {
System.out.println("Start of method: " + jp.getSignature().getName() + " of Class: "
+ jp.getTarget().getClass().getSimpleName());
System.out.println("Performance Number :" + performanceNum + "+ is :" + performanceName);
}
#After("performance()")
public void afterPerformance(JoinPoint jp,int performanceNum, String performanceName) {
System.out.println("End of method: " + jp.getSignature().getName() + " of Class: "
+ jp.getTarget().getClass().getSimpleName());
System.out.println("End of PerformanceName :" + performanceName);
System.out.println("CLAP CLAP CLAP!!!");
}
}
TestAOPMain.java
package com.aop.annotations.example4;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestAOPMain {
public static void main(String args[]) {
try {
ApplicationContext context = new ClassPathXmlApplicationContext("appContext4.xml");
Performance dancePerformance = context.getBean("dance", DancePerformance.class);
dancePerformance.buyTicket(100);
dancePerformance.perform(1,"Bhangra Dance");
dancePerformance.perform(2,"Garba Dance");
dancePerformance.perform(3,"Bharatnatyam Dance");
dancePerformance.perform(4,"Folk Dance");
Performance circusPerformance = (CircusPerformance) context.getBean("circus");
circusPerformance.buyTicket(200);
circusPerformance.perform(1,"Ball Juggling");
circusPerformance.perform(2,"Animal act");
circusPerformance.perform(3,"Rope Jump");
circusPerformance.perform(4,"Magic Show");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
aopContext4.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"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.aop.annotations.example4" />
<aop:aspectj-autoproxy proxy-target-class="true" />
<bean id = "dance" class="com.aop.annotations.example4.DancePerformance" />
<bean id = "circus" class="com.aop.annotations.example4.CircusPerformance" />
</beans>
Exception:
WARNING: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.context.event.internalEventListenerProcessor': Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: error at ::0 formal unbound in pointcut
Error creating bean with name 'org.springframework.context.event.internalEventListenerProcessor': Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: error at ::0 formal unbound in pointcut
If you do not need the method argument values in your aspect's advice, you should not use args(), but just specify the method signature in your pointcut like this:
#Pointcut("execution(* com.aop.annotations.example4.Performance.*(int, String))")
public void performance() {}
#Pointcut("execution(* com.aop.annotations.example4.Performance.*(int))")
public void buyTicket(int price) {}
Only if you do need access to the arguments, as your code implies, you should use args(), but then you also need to add the parameters to the pointcut, not just to the advice. If you define the pointcut directly in the advice, you only need to do it once. Defining pointcuts separately IMO is only helpful if you want to re-use the same pointcut in multiple advices in the same aspect. Anyway, what you want to do is this in order to fix your code (I did not run it, just writing this "hands-free"):
#Pointcut("execution(* com.aop.annotations.example4.Performance.*(..)) && args(performanceNum, performanceName)")
public void performance(int performanceNum, String performanceName) {}
#Pointcut("execution(* com.aop.annotations.example4.Performance.*(..)) && args(price)")
public void buyTicket(int price) {}
BTW, the error message "formal unbound in pointcut" means that you did not bind the formal parameters in your advice method's signature correctly in via args(), this(), target() or #target(). Or the other way around, the pointcut syntax is correct but the method signature is wrong.
I am trying to understand the sequence of static initialization, instance initialization, InitializingBean and BeanPostProcessor, so I created below example, everything is working except that BeanPostProcessor are not getting invoked, am I missing something?
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import org.springframework.core.io.FileSystemResource;
import org.springframework.stereotype.Component;
#Component
public class SpringTest {
#Autowired
Person person;
public static void main(String[] args) {
testApplicationContext();
}
private static void testApplicationContext() {
// here static and instance initializers of Person class will be invoked right away, even when we are not calling getBean method
ApplicationContext applicationContext = new FileSystemXmlApplicationContext("C:\\E_Drive\\Projects\\Workspace\\Test\\CS101\\src\\com\\learn\\stackoverflow\\general\\bean.xml");
ApplicationContext applicationContext2 = new FileSystemXmlApplicationContext("C:\\E_Drive\\Projects\\Workspace\\Test\\CS101\\src\\com\\learn\\stackoverflow\\general\\bean.xml");
// notice that above you are creating 2 ioc containers, and since they are different ioc containers so it is possible to have 2 singletons in JVM.
SpringTest springTest = (SpringTest) applicationContext.getBean("springTest");
}
}
Person class:
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
#Component
#Scope(value="singleton")
public class Person implements InitializingBean, BeanPostProcessor {
#Autowired
SpringTest springTest;
static{
System.out.println("Static initialization");
}
{
System.out.println("Instance initialization");
}
public void sayHello(){
System.out.println("Hello");
}
#Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean.afterPropertiesSet");
}
#Override
public Object postProcessAfterInitialization(Object arg0, String arg1) throws BeansException {
System.out.println("BeanPostProcessor.postProcessAfterInitialization : " + arg1);
return arg0;
}
#Override
public Object postProcessBeforeInitialization(Object arg0, String arg1) throws BeansException {
System.out.println("BeanPostProcessor.postProcessBeforeInitialization : " + arg1);
return arg0;
}
}
Bean XML file:
<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-3.0.xsd http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="com.learn.stackoverflow.general"/>
<context:annotation-config />
<!-- <bean id = "person" class = "com.learn.stackoverflow.general.Person" scope="singleton">
</bean> -->
<bean id = "springTest" class = "com.learn.stackoverflow.general.SpringTest" scope="singleton">
</bean>
</beans>
Output:
Static initialization
Instance initialization
InitializingBean.afterPropertiesSet
Instance initialization
InitializingBean.afterPropertiesSet
Is there anything else required for BeanPostProcessor methods to be invoked?
A bean cannot self-post-process, the post-processor needs to be a separate bean; see tutorial.
This is the XML file bean-jojo.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="vTypeCar" class="com.justPractise.ex01.Car" />
<bean id="vTypeBike" class="com.justPractise.ex01.MotorCycle" />
<bean id="vService" class="com.justPractise.ex01.VehicalService">
<property name="vehical" ref="vTypeBike" />
</bean>
<bean id="beanLifeCycleTest" class="com.jal.LifeCycleBeanP2">
<property name="justAParam" value="MICHEAL JACKSON" />
</bean>
<bean id="brun-p" class="com.justPractise.ex01.HALBrunPojo">
<constructor-arg value="234" />
</bean>
</beans>
I've registered on the following bean, on which I am trying constructor DI:
package com.justPractise.ex01;
public class HALBrunPojo {
private Integer num;
public HALBrunPojo(){
System.out.println(this.getClass().getName()+" INITIALISED ");
}
public HALBrunPojo(int num){
System.out.println(this.getClass().getName()+" PARAMETERISED..... INITIALISED "+num);
this.num = num;
}
public Integer getNum() {
return num;
}
public void setNum(Integer num) {
this.num = num;
}
}
As seen in the XML for the above bean declaration, I have specified the constructor-arg,
now this is the following code used which has the main method:
package com.justPractise.ex01;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainPractise01 {
/**
* #param args
*/
public static void main(String[] args) {
ApplicationContext ctx = null;
HALBrunPojo obj = null;
try{
ctx = new ClassPathXmlApplicationContext("bean-jojo.xml");
obj = (HALBrunPojo) ctx.getBean("brun-p");
System.out.println(" PARAM-VALUE "+(obj == null ? "0" : obj.getNum()));
}catch(Exception e){
e.printStackTrace();
}
}
}
When I try to run the above class from the command line, the output is
PARAM-VALUE 0
That means HALBrunPojo is null. After debugging I found out that if I commented the bean declaration of LifeCycleBeanP2 in bean-jojo.xml, like this:
<!--
<bean id="beanLifeCycleTest" class="com.jal.LifeCycleBeanP2">
<property name="justAParam" value="MICHEAL JACKSON" />
</bean>
-->
and then I run the program, I get desired output, i.e
PARAM-VALUE 234
Why so?, this is the code of the bean LifeCycleBeanP2.java:
package com.jal;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class LifeCycleBeanP2 implements BeanNameAware, BeanFactoryAware, BeanPostProcessor, InitializingBean, DisposableBean{
String justAParam;
public LifeCycleBeanP2(){
System.out.println(this.getClass().getName()+" INITIALISED...... ");
}
public String getJustAParam() {
return justAParam;
}
public void setJustAParam(String justAParam) {
System.out.println(" SETTER OF JustAParam ........ ");
this.justAParam = justAParam;
}
// method of BeanNameAware
#Override
public void setBeanName(String arg0) {
System.out.println(" IN SET BEAN-NAME "+arg0);
}
// method of BeanFactoryAware
#Override
public void setBeanFactory(BeanFactory arg0) throws BeansException {
System.out.println(" IN SET BEAN-FACTORY, "+arg0.getClass().getName());
}
// method of BeanPostProcessor
#Override
public Object postProcessAfterInitialization(Object arg0, String arg1)
throws BeansException {
System.out.println(" POST PROCESS AFTER INITIALISATION ");
return null;
}
// method of BeanPostProcessor
#Override
public Object postProcessBeforeInitialization(Object arg0, String arg1)
throws BeansException {
System.out.println(" POST PROCESS BEFORE INITIALISATION ");
return null;
}
//method of InitializingBean
#Override
public void afterPropertiesSet() throws Exception {
System.out.println(" AFTER PROPERTIES SET ");
}
//method of DisposableBean
#Override
public void destroy() throws Exception {
System.out.println(" BEAN "+this.getClass().getName()+" QUALIFIED FOR GARBAGE COLLECTION ");
}
}
What am I doing wrong?
A bean that implements a BeanPostProcessor interface is a special bean. It is passed a reference to all the other beans that are created by the context, it can modify them and return a different instance if required.
Whatever reference returned by the BeanPostProcessor will then be associated with the bean id.
In your LifeCycle class you are returning null - instead you should return the reference to the object that was passed to your methods. Change the two methods as follows, it should work as expected.
// method of BeanPostProcessor
#Override
public Object postProcessAfterInitialization(Object arg0, String arg1)
throws BeansException {
System.out.println(" POST PROCESS AFTER INITIALISATION ");
return arg0;
}
// method of BeanPostProcessor
#Override
public Object postProcessBeforeInitialization(Object arg0, String arg1)
throws BeansException {
System.out.println(" POST PROCESS BEFORE INITIALISATION ");
return arg0;
}