Below you will get a quick look to start with Core Spring -
First set your workspace like shown below, with all the shown jars.
First set your workspace like shown below, with all the shown jars.
Now below are the file details & have tried to explain in the comments also -
Below are the files which we will put in the hello package -
package hello;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.beans.factory.annotation.Required;
import testing.Singleton;
public class HelloWorld {
private String constrmsg;
public HelloWorld(String value, Singleton single) {
super();
constrmsg = value;
}
public String getmsg(){
return constrmsg;
}
private String today;
private String message;
// Though this property will be inherited from ParentHello but its getters & setters will be required to the value of the property in this bean
private String message1;
private ReferenceClass collect;
public void setMessage(String message){
this.message = message;
}
public void getMessage(){
System.out.println("Your Message : " + message);
}
public String getMessage1() {
return message1;
}
public void setMessage1(String message) {
// Here we are overidding the method defined in the ParentHello Class
this.message1 = message + " Overidden";
}
public ReferenceClass getCollect() {
return collect;
}
public void setCollect(ReferenceClass collect) {
this.collect = collect;
}
@PostConstruct
public void init(){
System.out.println("Bean is going through init.");
}
public void init1(){
System.out.println("Bean is going through init1.");
}
public void destroy(){
System.out.println("Bean will destroy now.");
}
@PreDestroy
public void destroys(){
System.out.println("In PreDestroy...");
}
public String getToday() {
return today;
}
/* The @Required annotation applies to bean property setter methods and it indicates that the affected bean property
must be populated in XML configuration file at configuration time
otherwise the container throws a BeanInitializationException exception.*/
@Required
public void setToday(String today) {
this.today = today;
}
}
package hello;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
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 } }
}
}
package hello;
public class ParentHello {
private String message1;
public String getMessage1() {
return message1;
}
public void setMessage1(String message) {
this.message1 = message;
}
}
package hello;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import testing.ReferBean;
public class ReferenceBean {
public String value = "ReferenceBean";
public int year = 2014;
private ReferBean referBean;
// Below is the way to autowire the property & using @Qualifier we are telling that which bean from the configuration file to be used.
// It helps when there are multiple beans of the same type defined in the configuration file & we want to use a particular bean
@Autowired
@Qualifier("referBean1")
private ReferBean referBean1;
public ReferBean getReferBean() {
return referBean;
}
// Here the bean with name referbean will be used from the configuration file
// If we remove the input parameter then the property will not be set as by default, the @Autowired annotation implies the dependency is required
// similar to @Required annotation,
@Autowired
public void setReferBean(ReferBean referBean) {
this.referBean = referBean;
}
public ReferBean getReferBean1() {
return referBean1;
}
// Below will work even if you do not pass any value
/*@Autowired(required=false)
public void setReferBean1() {
this.referBean1 = new ReferBean();
}*/
}
package hello;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class ReferenceClass {
private List list;
private Set set;
private Map map;
private Properties prop;
public List getList() {
return list;
}
public void setList(List list) {
this.list = list;
}
public Set getSet() {
return set;
}
public void setSet(Set set) {
this.set = set;
}
public Map getMap() {
return map;
}
public void setMap(Map map) {
this.map = map;
}
public Properties getProp() {
return prop;
}
public void setProp(Properties prop) {
this.prop = prop;
}
}
Now below also I have put in the hello package as the executor file, though you can put this in any other package also but will have to import all the above files in that case -
package hello;
import java.io.File;
import java.util.HashSet;
import java.util.Set;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;
import testing.Singleton;
public class MainApp {
public static void main(String[] args) {
/*The ApplicationContext container includes all functionality of the BeanFactory container,
so it is generally recommended over the BeanFactory.*/
// ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
// In FileSystemXmlApplicationContext one has to give the complete path for the xml File. In path one has to use \\ or / like shown below
/*We can use ApplicationContext instead of AbstractApplicationContext shown below, if don't want to register
the shutdown hook*/
AbstractApplicationContext context = new FileSystemXmlApplicationContext("D:\\Eclipse Workspaces\\Spring\\Practise\\src\\Beans.xml");
/*BeanFactory can still be used for light weight applications like mobile devices or
applet based applications where data volume and speed is significant.
The most commonly used BeanFactory implementation is the XmlBeanFactoryclass.
*/
// XmlBeanFactory context = new XmlBeanFactory (new ClassPathResource("Beans.xml"));
HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
HelloWorld obj1 = (HelloWorld) context.getBean("helloWorld");
obj.getMessage();
System.out.println("Value by overridden method of parent- " + obj.getMessage1());
/*Below will return true as by default scope of the beans is Singleton
But will return false if we add scope="prototye" in beans.xml after class name*/
System.out.println("Are the two objects provided by Spring equal? " + (obj == obj1));
// Gives the value set by the constructor
System.out.println("Value set by the constructor- " + obj.getmsg());
// Information about the list in the bean
System.out.println("Values in the list- " + obj.getCollect().getList());
System.out.println("Value in the list at index 0 " + obj.getCollect().getList().get(0));
System.out.println("Value in the list at index 1 " + obj.getCollect().getList().get(1));
// Referencing the bean in the list
System.out.println("Value in the object in the list at index 2 " + ((ReferenceBean)obj.getCollect().getList().get(2)).value);
// Information about the set in the bean
System.out.println("Values in the set- " + obj.getCollect().getSet());
System.out.println("Size of the set : " + ((HashSet)obj.getCollect().getSet()).size());
// Set can have duplicate beans if we create them
Set set = new HashSet();
set.add(new ReferenceBean());
set.add(new ReferenceBean());
System.out.println("Values in the set when we created the beans " + set);
// Information about the Map in the bean.
// The value returned by the map needs to be cast to the correct Class type as Map defined in this bean can have any type of keys or values
System.out.println("Fetching the value from the collection " + ((ReferenceBean)obj.getCollect().getMap().get("Reference")).value);
// Below statement will give null as the object passed as the key is not provided by Spring, so it is different from the object
// used as the key in the Map
System.out.println("Value is null as the object given as key is not created by Spring " + obj.getCollect().getMap().get(new ReferenceBean()));
// To get the value using an object from the map, then we need to get that object from Spring like shown below
// But if the scope of ReferenceBean in beans.xml is not singleton than it will also produce value as null because Spring also will create a new object
// for every request
ReferenceBean rb = (ReferenceBean)context.getBean("reference");
System.out.println("Value will be null here as the reason given in the comments : " + obj.getCollect().getMap().get(rb));
// Below we are testing the singleton behaviour in bit complex way
Singleton single1 = (Singleton)context.getBean("singleton");
Singleton single2 = (Singleton)context.getBean("singleton");
System.out.println("Is it singleton really? " + (single1==single2));
// Now play with the reference in the above singleton bean
single1.getReference().value = "Changing";
// Please note that ReferenceBean class object used in Singleton bean is not configured as singleton,
// but still when we change the value using single1, value referred by the ReferenceBean object in single2 also changes
System.out.println("Value is getting impacted here also as it is singleton managed by Spring " + single2.getReference().value);
// To show the purpose of @Required annotation
System.out.println("To show the purpose of @Required annotation : " + obj.getToday());
// To show the purpose of @Autowired annotation
System.out.println("Fetching the autowired bean : " + rb.getReferBean().getName());
System.out.println("Fetching the autowired bean : " + rb.getReferBean1().getName());
System.out.println("Accessing the value in ParentHello bean using @Autowired annotation on properties : " + rb.getReferBean().parent.getMessage1());
// If we don't use & register the below hook the destroy method of the bean will not be called
context.registerShutdownHook();
}
}
Now below files are put in testing package -
package testing;
import hello.ParentHello;
import org.springframework.beans.factory.annotation.Autowired;
public class ReferBean {
private String name;
// Here we can autowire only those type of properties which are configured in configuration xml file, i.e. we can use primitive type or String or Wrapper types
@Autowired
public ParentHello parent;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package testing;
import javax.annotation.Resource;
import hello.ReferenceBean;
public class Singleton {
// If no 'reference' is specified explicitly, the default name is derived from the field name or setter method.
// In case of a field, it takes the field name; in case of a setter method, it takes the bean property name.
// It can be applied to field like shown below or to the setter method
// You can say, it follows by-name autowiring semantics
@Resource(name="reference")
private ReferenceBean reference;
private String name;
public ReferenceBean getReference() {
return reference;
}
public void setReference(ReferenceBean reference) {
this.reference = reference;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Below are the configuration files required -
Beans.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/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
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<context:annotation-config/>
<!-- If the below line is added in the end of the above line then it will
be applicable for all the beans & no need to specify for each bean separately.
But if any bean has specified init & destroy method in its definition like
shown below, then its methods will be executed for that bean -->
<!-- default-init-method="init" default-destroy-method="destroy" -->
<import resource="AOP-Beans.xml" />
<!-- Beans are created for the aspects -->
<bean id="helloworldlogging" class="xmlAspects.HelloWorldLogging"/>
<bean id="referencebeanlogging" class="xmlAspects.ReferenceBeanLogging"/>
<!-- constructor autowiring & same restrictions apply to it as with byType autowiring -->
<bean id="helloWorld" class="hello.HelloWorld" init-method="init1"
destroy-method="destroy" parent="parent" autowire="constructor">
<constructor-arg value="Constructor value"/>
<property name="message" value="Hello Nitin!" />
<property name="collect" ref="refer" />
<property name="today" value="Friday" />
</bean>
<!-- As hello.InitHelloWorld implements the BeanPostProcessor, it will be
executed before & after initialization of every bean in the configuration
XML -->
<bean class="hello.InitHelloWorld" />
<bean id="parent" class="hello.ParentHello">
<property name="message1" value="In ParentHello"/>
</bean>
<bean id="refer" class="hello.ReferenceClass">
<property name="list">
<!-- List tag can be ignored if we give one value & this value then can be accessed by any index number i.e. 0 or 1 or 2 or... in the list -->
<list>
<value>In List</value>
<value>"In List With Quotes"</value>
<ref bean="reference"/>
</list>
</property>
<property name="set">
<set>
<value>INDIA</value>
<value>Pakistan</value>
<value>USA</value>
<value>USA</value>
<!-- Below beans are being created -->
<ref bean="reference"/>
<ref bean="reference"/>
</set>
</property>
<property name="map">
<map>
<entry key-ref="reference" value="Key is reference"/>
<entry key="Reference" value-ref="reference"/>
</map>
</property>
</bean>
<bean id="reference" class="hello.ReferenceBean" scope="prototype"></bean>
<!-- reference1 bean -->
<bean id="reference1" class="hello.ReferenceBean" scope="prototype"></bean>
<!-- If we uncomment this byType autowiring & comment the byName autowiring then will get the exceptions as Spring will not be able to decide on the
bean to be autowired here as we have 2 beans of same type but with different names. So such care needs to be taken in case of byType autowiring-->
<!-- <bean id="singleton" class="testing.Singleton" autowire="byType"> -->
<!-- See how the autowiring i.e. byName is used -->
<bean id="singleton" class="testing.Singleton" autowire="byName">
<property name="name" value="Singleton"/>
</bean>
<!-- Though this bean is autowired in ReferenceBean but still it depends on the bean name used in the method as input parameter.
So that particular bean will picked & used, whose name has been used as the input parameter-->
<bean id="referBean" class="testing.ReferBean">
<property name="name" value="In ReferBean"/>
</bean>
<bean id="referBean1" class="testing.ReferBean" autowire="byName">
<property name="name" value="In ReferBean1"/>
</bean>
</beans>
AOP-Beans.xml
<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-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<!-- We are weaving & configuring the aspects. -->
<!-- We can have multiple pointcuts for different classes & methods like
shown below -->
<aop:config>
<aop:aspect id="helloworldlog" ref="helloworldlogging">
<aop:pointcut id="helloworld" expression="execution(* hello.HelloWorld.get*(..))" />
<aop:before pointcut-ref="helloworld" method="beforeAdvice" />
<aop:after pointcut-ref="helloworld" method="afterAdvice" />
<aop:after-returning pointcut-ref="helloworld"
returning="retVal" method="afterReturningAdvice" />
<aop:after-throwing pointcut-ref="helloworld"
throwing="ex" method="AfterThrowingAdvice" />
</aop:aspect>
<aop:aspect id="referencebeanlog" ref="referencebeanlogging">
<!-- Only below way is not causing any exception else if mention the method
then exception is occurring & don't know the reason -->
<aop:pointcut id="referencebean"
expression="execution(* hello.ReferenceBean.*.*(..))" />
<aop:around pointcut-ref="referencebean" method="aroundAdvice" />
</aop:aspect>
</aop:config>
</beans>
Below is the output when we execute the MainApp.java file, as created above -
BeforeInitialization : parent
AfterInitialization : parent
BeforeInitialization : referBean1
AfterInitialization : referBean1
BeforeInitialization : referBean
AfterInitialization : referBean
BeforeInitialization : reference
AfterInitialization : reference
BeforeInitialization : reference
AfterInitialization : reference
BeforeInitialization : singleton
AfterInitialization : singleton
BeforeInitialization : reference
AfterInitialization : reference
BeforeInitialization : reference
AfterInitialization : reference
BeforeInitialization : reference
AfterInitialization : reference
BeforeInitialization : reference
AfterInitialization : reference
BeforeInitialization : refer
AfterInitialization : refer
BeforeInitialization : helloWorld
Bean is going through init.
Bean is going through init1.
AfterInitialization : helloWorld
Your Message : Hello Nitin!
Value by overridden method of parent- In ParentHello Overidden
Are the two objects provided by Spring equal? true
Value set by the constructor- Constructor value
Values in the list- [In List, "In List With Quotes", hello.ReferenceBean@16a9b9c]
Value in the list at index 0 In List
Value in the list at index 1 "In List With Quotes"
Value in the object in the list at index 2 ReferenceBean
Values in the set- [INDIA, Pakistan, USA, hello.ReferenceBean@6210fb]
Size of the set : 4
Values in the set when we created the beans [hello.ReferenceBean@e2291, hello.ReferenceBean@1ff92f5]
Fetching the value from the collection ReferenceBean
Value is null as the object given as key is not created by Spring null
BeforeInitialization : reference
AfterInitialization : reference
Value will be null here as the reason given in the comments : null
Is it singleton really? true
Value is getting impacted here also as it is singleton managed by Spring Changing
To show the purpose of @Required annotation : Friday
Fetching the autowired bean : In ReferBean
Fetching the autowired bean : In ReferBean1
Accessing the value in ParentHello bean using @Autowired annotation on properties : In ParentHello
Jul 21, 2014 2:45:29 AM org.springframework.context.support.AbstractApplicationContext doClose
INFO: Closing org.springframework.context.support.FileSystemXmlApplicationContext@17fa65e: startup date [Mon Jul 21 02:45:28 GMT 2014]; root of context hierarchy
In PreDestroy...
Bean will destroy now.
I hope that above example will help to understand some basics about Core Spring. Next I will give the example about how to work without any configuration xml file. Keep learning :)
Below are the files which we will put in the hello package -
package hello;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.beans.factory.annotation.Required;
import testing.Singleton;
public class HelloWorld {
private String constrmsg;
public HelloWorld(String value, Singleton single) {
super();
constrmsg = value;
}
public String getmsg(){
return constrmsg;
}
private String today;
private String message;
// Though this property will be inherited from ParentHello but its getters & setters will be required to the value of the property in this bean
private String message1;
private ReferenceClass collect;
public void setMessage(String message){
this.message = message;
}
public void getMessage(){
System.out.println("Your Message : " + message);
}
public String getMessage1() {
return message1;
}
public void setMessage1(String message) {
// Here we are overidding the method defined in the ParentHello Class
this.message1 = message + " Overidden";
}
public ReferenceClass getCollect() {
return collect;
}
public void setCollect(ReferenceClass collect) {
this.collect = collect;
}
@PostConstruct
public void init(){
System.out.println("Bean is going through init.");
}
public void init1(){
System.out.println("Bean is going through init1.");
}
public void destroy(){
System.out.println("Bean will destroy now.");
}
@PreDestroy
public void destroys(){
System.out.println("In PreDestroy...");
}
public String getToday() {
return today;
}
/* The @Required annotation applies to bean property setter methods and it indicates that the affected bean property
must be populated in XML configuration file at configuration time
otherwise the container throws a BeanInitializationException exception.*/
@Required
public void setToday(String today) {
this.today = today;
}
}
package hello;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
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 } }
}
}
package hello;
public class ParentHello {
private String message1;
public String getMessage1() {
return message1;
}
public void setMessage1(String message) {
this.message1 = message;
}
}
package hello;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import testing.ReferBean;
public class ReferenceBean {
public String value = "ReferenceBean";
public int year = 2014;
private ReferBean referBean;
// Below is the way to autowire the property & using @Qualifier we are telling that which bean from the configuration file to be used.
// It helps when there are multiple beans of the same type defined in the configuration file & we want to use a particular bean
@Autowired
@Qualifier("referBean1")
private ReferBean referBean1;
public ReferBean getReferBean() {
return referBean;
}
// Here the bean with name referbean will be used from the configuration file
// If we remove the input parameter then the property will not be set as by default, the @Autowired annotation implies the dependency is required
// similar to @Required annotation,
@Autowired
public void setReferBean(ReferBean referBean) {
this.referBean = referBean;
}
public ReferBean getReferBean1() {
return referBean1;
}
// Below will work even if you do not pass any value
/*@Autowired(required=false)
public void setReferBean1() {
this.referBean1 = new ReferBean();
}*/
}
package hello;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class ReferenceClass {
private List list;
private Set set;
private Map map;
private Properties prop;
public List getList() {
return list;
}
public void setList(List list) {
this.list = list;
}
public Set getSet() {
return set;
}
public void setSet(Set set) {
this.set = set;
}
public Map getMap() {
return map;
}
public void setMap(Map map) {
this.map = map;
}
public Properties getProp() {
return prop;
}
public void setProp(Properties prop) {
this.prop = prop;
}
}
Now below also I have put in the hello package as the executor file, though you can put this in any other package also but will have to import all the above files in that case -
package hello;
import java.io.File;
import java.util.HashSet;
import java.util.Set;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;
import testing.Singleton;
public class MainApp {
public static void main(String[] args) {
/*The ApplicationContext container includes all functionality of the BeanFactory container,
so it is generally recommended over the BeanFactory.*/
// ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
// In FileSystemXmlApplicationContext one has to give the complete path for the xml File. In path one has to use \\ or / like shown below
/*We can use ApplicationContext instead of AbstractApplicationContext shown below, if don't want to register
the shutdown hook*/
AbstractApplicationContext context = new FileSystemXmlApplicationContext("D:\\Eclipse Workspaces\\Spring\\Practise\\src\\Beans.xml");
/*BeanFactory can still be used for light weight applications like mobile devices or
applet based applications where data volume and speed is significant.
The most commonly used BeanFactory implementation is the XmlBeanFactoryclass.
*/
// XmlBeanFactory context = new XmlBeanFactory (new ClassPathResource("Beans.xml"));
HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
HelloWorld obj1 = (HelloWorld) context.getBean("helloWorld");
obj.getMessage();
System.out.println("Value by overridden method of parent- " + obj.getMessage1());
/*Below will return true as by default scope of the beans is Singleton
But will return false if we add scope="prototye" in beans.xml after class name*/
System.out.println("Are the two objects provided by Spring equal? " + (obj == obj1));
// Gives the value set by the constructor
System.out.println("Value set by the constructor- " + obj.getmsg());
// Information about the list in the bean
System.out.println("Values in the list- " + obj.getCollect().getList());
System.out.println("Value in the list at index 0 " + obj.getCollect().getList().get(0));
System.out.println("Value in the list at index 1 " + obj.getCollect().getList().get(1));
// Referencing the bean in the list
System.out.println("Value in the object in the list at index 2 " + ((ReferenceBean)obj.getCollect().getList().get(2)).value);
// Information about the set in the bean
System.out.println("Values in the set- " + obj.getCollect().getSet());
System.out.println("Size of the set : " + ((HashSet)obj.getCollect().getSet()).size());
// Set can have duplicate beans if we create them
Set set = new HashSet();
set.add(new ReferenceBean());
set.add(new ReferenceBean());
System.out.println("Values in the set when we created the beans " + set);
// Information about the Map in the bean.
// The value returned by the map needs to be cast to the correct Class type as Map defined in this bean can have any type of keys or values
System.out.println("Fetching the value from the collection " + ((ReferenceBean)obj.getCollect().getMap().get("Reference")).value);
// Below statement will give null as the object passed as the key is not provided by Spring, so it is different from the object
// used as the key in the Map
System.out.println("Value is null as the object given as key is not created by Spring " + obj.getCollect().getMap().get(new ReferenceBean()));
// To get the value using an object from the map, then we need to get that object from Spring like shown below
// But if the scope of ReferenceBean in beans.xml is not singleton than it will also produce value as null because Spring also will create a new object
// for every request
ReferenceBean rb = (ReferenceBean)context.getBean("reference");
System.out.println("Value will be null here as the reason given in the comments : " + obj.getCollect().getMap().get(rb));
// Below we are testing the singleton behaviour in bit complex way
Singleton single1 = (Singleton)context.getBean("singleton");
Singleton single2 = (Singleton)context.getBean("singleton");
System.out.println("Is it singleton really? " + (single1==single2));
// Now play with the reference in the above singleton bean
single1.getReference().value = "Changing";
// Please note that ReferenceBean class object used in Singleton bean is not configured as singleton,
// but still when we change the value using single1, value referred by the ReferenceBean object in single2 also changes
System.out.println("Value is getting impacted here also as it is singleton managed by Spring " + single2.getReference().value);
// To show the purpose of @Required annotation
System.out.println("To show the purpose of @Required annotation : " + obj.getToday());
// To show the purpose of @Autowired annotation
System.out.println("Fetching the autowired bean : " + rb.getReferBean().getName());
System.out.println("Fetching the autowired bean : " + rb.getReferBean1().getName());
System.out.println("Accessing the value in ParentHello bean using @Autowired annotation on properties : " + rb.getReferBean().parent.getMessage1());
// If we don't use & register the below hook the destroy method of the bean will not be called
context.registerShutdownHook();
}
}
Now below files are put in testing package -
package testing;
import hello.ParentHello;
import org.springframework.beans.factory.annotation.Autowired;
public class ReferBean {
private String name;
// Here we can autowire only those type of properties which are configured in configuration xml file, i.e. we can use primitive type or String or Wrapper types
@Autowired
public ParentHello parent;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package testing;
import javax.annotation.Resource;
import hello.ReferenceBean;
public class Singleton {
// If no 'reference' is specified explicitly, the default name is derived from the field name or setter method.
// In case of a field, it takes the field name; in case of a setter method, it takes the bean property name.
// It can be applied to field like shown below or to the setter method
// You can say, it follows by-name autowiring semantics
@Resource(name="reference")
private ReferenceBean reference;
private String name;
public ReferenceBean getReference() {
return reference;
}
public void setReference(ReferenceBean reference) {
this.reference = reference;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Below are the configuration files required -
Beans.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/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
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<context:annotation-config/>
<!-- If the below line is added in the end of the above line then it will
be applicable for all the beans & no need to specify for each bean separately.
But if any bean has specified init & destroy method in its definition like
shown below, then its methods will be executed for that bean -->
<!-- default-init-method="init" default-destroy-method="destroy" -->
<import resource="AOP-Beans.xml" />
<!-- Beans are created for the aspects -->
<bean id="helloworldlogging" class="xmlAspects.HelloWorldLogging"/>
<bean id="referencebeanlogging" class="xmlAspects.ReferenceBeanLogging"/>
<!-- constructor autowiring & same restrictions apply to it as with byType autowiring -->
<bean id="helloWorld" class="hello.HelloWorld" init-method="init1"
destroy-method="destroy" parent="parent" autowire="constructor">
<constructor-arg value="Constructor value"/>
<property name="message" value="Hello Nitin!" />
<property name="collect" ref="refer" />
<property name="today" value="Friday" />
</bean>
<!-- As hello.InitHelloWorld implements the BeanPostProcessor, it will be
executed before & after initialization of every bean in the configuration
XML -->
<bean class="hello.InitHelloWorld" />
<bean id="parent" class="hello.ParentHello">
<property name="message1" value="In ParentHello"/>
</bean>
<bean id="refer" class="hello.ReferenceClass">
<property name="list">
<!-- List tag can be ignored if we give one value & this value then can be accessed by any index number i.e. 0 or 1 or 2 or... in the list -->
<list>
<value>In List</value>
<value>"In List With Quotes"</value>
<ref bean="reference"/>
</list>
</property>
<property name="set">
<set>
<value>INDIA</value>
<value>Pakistan</value>
<value>USA</value>
<value>USA</value>
<!-- Below beans are being created -->
<ref bean="reference"/>
<ref bean="reference"/>
</set>
</property>
<property name="map">
<map>
<entry key-ref="reference" value="Key is reference"/>
<entry key="Reference" value-ref="reference"/>
</map>
</property>
</bean>
<bean id="reference" class="hello.ReferenceBean" scope="prototype"></bean>
<!-- reference1 bean -->
<bean id="reference1" class="hello.ReferenceBean" scope="prototype"></bean>
<!-- If we uncomment this byType autowiring & comment the byName autowiring then will get the exceptions as Spring will not be able to decide on the
bean to be autowired here as we have 2 beans of same type but with different names. So such care needs to be taken in case of byType autowiring-->
<!-- <bean id="singleton" class="testing.Singleton" autowire="byType"> -->
<!-- See how the autowiring i.e. byName is used -->
<bean id="singleton" class="testing.Singleton" autowire="byName">
<property name="name" value="Singleton"/>
</bean>
<!-- Though this bean is autowired in ReferenceBean but still it depends on the bean name used in the method as input parameter.
So that particular bean will picked & used, whose name has been used as the input parameter-->
<bean id="referBean" class="testing.ReferBean">
<property name="name" value="In ReferBean"/>
</bean>
<bean id="referBean1" class="testing.ReferBean" autowire="byName">
<property name="name" value="In ReferBean1"/>
</bean>
</beans>
AOP-Beans.xml
<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-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<!-- We are weaving & configuring the aspects. -->
<!-- We can have multiple pointcuts for different classes & methods like
shown below -->
<aop:config>
<aop:aspect id="helloworldlog" ref="helloworldlogging">
<aop:pointcut id="helloworld" expression="execution(* hello.HelloWorld.get*(..))" />
<aop:before pointcut-ref="helloworld" method="beforeAdvice" />
<aop:after pointcut-ref="helloworld" method="afterAdvice" />
<aop:after-returning pointcut-ref="helloworld"
returning="retVal" method="afterReturningAdvice" />
<aop:after-throwing pointcut-ref="helloworld"
throwing="ex" method="AfterThrowingAdvice" />
</aop:aspect>
<aop:aspect id="referencebeanlog" ref="referencebeanlogging">
<!-- Only below way is not causing any exception else if mention the method
then exception is occurring & don't know the reason -->
<aop:pointcut id="referencebean"
expression="execution(* hello.ReferenceBean.*.*(..))" />
<aop:around pointcut-ref="referencebean" method="aroundAdvice" />
</aop:aspect>
</aop:config>
</beans>
Below is the output when we execute the MainApp.java file, as created above -
BeforeInitialization : parent
AfterInitialization : parent
BeforeInitialization : referBean1
AfterInitialization : referBean1
BeforeInitialization : referBean
AfterInitialization : referBean
BeforeInitialization : reference
AfterInitialization : reference
BeforeInitialization : reference
AfterInitialization : reference
BeforeInitialization : singleton
AfterInitialization : singleton
BeforeInitialization : reference
AfterInitialization : reference
BeforeInitialization : reference
AfterInitialization : reference
BeforeInitialization : reference
AfterInitialization : reference
BeforeInitialization : reference
AfterInitialization : reference
BeforeInitialization : refer
AfterInitialization : refer
BeforeInitialization : helloWorld
Bean is going through init.
Bean is going through init1.
AfterInitialization : helloWorld
Your Message : Hello Nitin!
Value by overridden method of parent- In ParentHello Overidden
Are the two objects provided by Spring equal? true
Value set by the constructor- Constructor value
Values in the list- [In List, "In List With Quotes", hello.ReferenceBean@16a9b9c]
Value in the list at index 0 In List
Value in the list at index 1 "In List With Quotes"
Value in the object in the list at index 2 ReferenceBean
Values in the set- [INDIA, Pakistan, USA, hello.ReferenceBean@6210fb]
Size of the set : 4
Values in the set when we created the beans [hello.ReferenceBean@e2291, hello.ReferenceBean@1ff92f5]
Fetching the value from the collection ReferenceBean
Value is null as the object given as key is not created by Spring null
BeforeInitialization : reference
AfterInitialization : reference
Value will be null here as the reason given in the comments : null
Is it singleton really? true
Value is getting impacted here also as it is singleton managed by Spring Changing
To show the purpose of @Required annotation : Friday
Fetching the autowired bean : In ReferBean
Fetching the autowired bean : In ReferBean1
Accessing the value in ParentHello bean using @Autowired annotation on properties : In ParentHello
Jul 21, 2014 2:45:29 AM org.springframework.context.support.AbstractApplicationContext doClose
INFO: Closing org.springframework.context.support.FileSystemXmlApplicationContext@17fa65e: startup date [Mon Jul 21 02:45:28 GMT 2014]; root of context hierarchy
In PreDestroy...
Bean will destroy now.
I hope that above example will help to understand some basics about Core Spring. Next I will give the example about how to work without any configuration xml file. Keep learning :)