Spring / Spring Beans
The Spring Beans are nothing but Java Objects that forms the backbone of a Spring application. Those beans are instantiated, assembled, and managed by the Spring IoC container. These beans are created using the configuration metadata definition supplied to the container, for example, in the form of XML
All the beans in spring framework are singleton beans by default. An attribute in xml bean tag named "singleton" is set to true then bean becomes singleton and if set to false then the bean becomes a prototype bean.
A Spring Bean definition holds all the configuration metadata required for the container to understand how to create a bean, manage its lifecycle and its dependencies.
1. singleton : Returns a single bean instance per Spring IOC container.(default scope)
2. prototype : Returns a new bean instance each time when requested.
3. request : Returns a single bean instance per HTTP request.
4. session : Returns a single bean instance per HTTP session.
5. global session : Return a single bean instance per global HTTP session and only valid when used in portlet context.
There are 3 ways to provide configuration metadata to the Spring Container.
- XML based configuration file.
- Annotation-based configuration.
- Java-based configuration.
While defining a bean in Spring xml configuration, the scope also can be declared for the bean. The scope attribute of the bean defines its scope.
The scope attribute takes one of the five values: singleton, prototype, request, session and global session
.
The spring container loads the bean definition from the XML file and instantiates the bean. Also it initializes the properties of the bean using Dependency Injection (DI) that are specified in the bean definition in XML file.
Once spring container created the bean, Spring bean factory will control and held responsible for managing the life cycle of beans.
Once a bean is instantiated by the spring container, some of the initialization need to be performed to get it into a usable state. Similarly, when the bean is no longer required and about to be removed from the container, some cleanup process may be involved.
The life cycle of beans consist of several call back methods that are broadly categorized into two groups.
- Post-initialization callback methods.
- Pre-destruction callback methods.
No. The singleton scoped beans are not thread-safe in Spring framework.
There are 2 important bean lifecycle methods.
The setup method called when the bean is loaded into the container.
The teardown method which is invoked when the bean is unloaded from the container.
The bean XML tag has two important attributes init-method and destroy-method to define your custom initialization and destroy methods. There are also the equivalent annotations @PostConstruct and @PreDestroy.
Inner beans are spring beans that are used as a property of another spring bean.
Spring's XML-based configuration metadata provides the use of <bean/> element inside the <property/> or <constructor-arg/> elements of a bean definition to declare inner beans. Inner beans are always anonymous and it is always scoped as prototypes.
-
Overriding: You can still specify dependencies using
and settings which will always override autowiring. - Primitive data types: You cannot autowire simple properties such as primitives.
- Confusing nature: Autowiring is less exact than explicit wiring, so if possible prefer using explicit wiring.
<props>
tag can be used to inject properties to a spring bean as shown below.
The @Required annotation applies to bean property setter methods and it indicates that the represented bean property is required and must be initialized in XML configuration file at configuration time otherwise the container will throw a BeanInitializationException
exception.
public class Employee { private Integer age; private String name; public Integer getAge() { return age; } @Required public void setAge(Integer age) { this.age = age; } }
The RequiredAnnotation BeanPostProcessor bean post processor checks if all the bean properties with the @Required annotation have been set. To enable this bean post processor, you must register it in the Spring IoC container.
<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor" />
The @Autowired
annotation provides fine-grained control over where and how autowiring should be accomplished. The @Autowired annotation can be used to autowire a bean on the setter method, constructor, a property or methods with arbitrary names and/or multiple arguments.
Autowired annotation on setter methods.
The @Autowired annotation can be applied on setter methods that eliminates the <property> element in XML configuration file. Spring performs byType autowiring on the property setter method when marked as Autowired.
Autowired annotation on bean properties.
Autowired annotation on properties eliminate the need of setter methods. When value for the autowired properties is set using <property> in the xml configuration, Spring will automatically assign those properties with the passed values or references.
Autowired on Constructors.
A @Autowired constructor indicates that the constructor should be autowired when creating the bean, even if no <constructor-arg> elements are used while configuring the bean in XML file.
By default, the @Autowired annotation sets the dependency as mandatory similar to @Required annotation, however, the default behavior can be turned off by using required = false option with @Autowired.
javax.annotation.@Resource annotation can be applied on fields or setter methods for dependency injection and it follows by-name autowiring semantics, name extracted from the name of the annotated setter/field or from the 'name' attribute. The @Resource annotation takes a 'name' attribute which will be interpreted as the bean name to be injected.
@Resource is specified by the JSR-250.
Using bean xml tag, a spring bean can be configured. Bean tag has id
attribute that specifies the bean name and the class
attribute represents the fully qualified class name.
The spring DAO class do not throw any specific exceptions such as SQLException instead it throws exceptions that are subclasses of DataAccessException.
There are 3 different ways to configure a class as Spring Bean.
XML Configuration is the most popular configuration. The bean element tag is used in xml context file to configure a Spring Bean.
Using Java Based Configuration, you can configure a Spring bean using @Bean annotation. This annotation is used with @Configuration classes to configure a spring bean.
Annotation Based Configuration facilitates @Component, @Service, @Repository and @Controller annotations with classes to configure them to be as spring bean. For these, we would need to provide base package location to scan for these classes
Per the Spring 3 documentation, 'you use the id and/or name attributes to specify the bean identifier(s)'.
The name
attribute behaves and functions similar to id
attribute on a bean but it allows the bean unique identifier to contain special characters. Special characters like #, @, $, *, / are not allowed in the id attribute.
The name attribute allows for multiple 'aliases' that becomes a collection of identifiers that can be used to identify the bean whereas there can be only one id per container.
<bean id="myBeanID" name = "myBean1,myBean2,myBean2" class="net.javapedia.bean.EmpBean">
The default scope of Spring bean is singleton, which means that there be only one instance per context. Having a bean class level variable that any thread can update will lead to inconsistent data. Hence in default mode spring beans are not thread-safe.
@autowired wires by bean type whereas @resource wires by name.
Using @Qualifier along with the @Autowired functions exactly similar to the @Resource annotation.
lazy-init attribute of <bean> tag is used to specify whether a spring bean is to be lazily initialized or not.
BeanFactory initializes all the spring beans lazily while ApplicationContext initializes all singleton spring beans eagerly. To make ApplicationContext to initialize the all the spring bean lazily, lazy-init attribute need to be set to true.
Following are the allowed values for lazy-init attribute.
true - lazy, IOC container creates the bean when it is first requested.
false - eager, IOC container creates the bean at startup.
default - refers to the default-lazy-init attribute specified for the <beans>
No. An inner bean cannot be accessed even if the id attribute is defined, getBean ("theInnerId") will fail with NoSuchBeanDefinitionException
.
Spring bean can exhibit inheritance behavior by defining parent and child beans. The parent beans are configured using the abstract attribute value being set to true. A child bean can be configured using parent attribute on bean tag, parent bean id as its value.
A child bean definition inherits configuration data from a parent definition. The child definition can override few values ,add others as needed.
Spring Bean definition inheritance has nothing to do with Java class inheritance but inheritance concept is similar. You can define a parent bean definition as a template and other child beans can inherit required configuration from the parent bean.
Bean definition template also referred as parent beans can be used to define common bean definitions shared by other child beans without redefining it.
While defining a Bean Definition Template, class attribute may not be defined and should specify abstract attribute with its value as true.
The parent bean cannot be instantiated on its own because it is incomplete, and also it is explicitly marked as abstract.
The spring bean definition with abstract
attribute as true
with no class attribute are meant for only inheritance and sharing of properties that are termed as pure definition template.
Yes. Some spring beans are not required to be accessed by any other beans in the context file or by programmatically. So it does not require an id or name attribute as they are not referenced.
No. @Autowired annotation expects a bean of the type to present in the applicationContext.
Using the prototype bean scope, one can define a stateful bean. Prototype scoped beans are instantiated every time it is requested.
Prototype scope creates a new instance everytime getBean
method is invoked on the ApplicationContext. Whereas for request scope, only one instance is created for an HttpRequest.
So in a HttpRequest, if the getBean
method is called twice on Application and there will be only one bean instantiated and reused, whereas the bean scoped to Prototype in that same single HttpRequest would get 2 different instances.
The Spring bean configuration file defines all the beans that will be initialized by Spring Context. When an instance of Spring ApplicationContext is created, it reads the spring bean xml file and initialize all of them. Once the context is initialized, it can be used to get different bean instances.
Consider a scenario where Class A requires an instance of class B through constructor injection, and class B requires an instance of class A through constructor injection. If you configure beans for the classes A and B to be injected into each other, the Spring IoC container detects this circular reference at runtime and throws a BeanCurrentlyInCreationException.
The easiest solution to resolve the circular dependency issues would be editing the classes to have the dependency set by setters rather than constructor.
public class A { public A() { System.out.println("Creating instance of A"); } private B b; public void setB(B b) { System.out.println("Setting dependency B of A instance"); this.b = b; } }
public class B { public B() { System.out.println("Creating instance of B"); } private A a; public void setA(A a) { System.out.println("Setting dependency A of B instance"); this.a = a; } }
<bean id="a" class="mypackage.A"> <property name="b" ref="b" /> </bean> <bean id="b" class="mypackage.B"> <property name="a" ref="a" /> </bean>
No, not necessarily. A spring bean marked as abstract cannot be instantiated, repurpose this bean reference as parent to other child bean definition.
<util:set> <util:list>
and <util:map>
tag specifies the collection for the spring bean and the set-class property of the tag specifies the particular implementation of collection class you prefer.
<util:list set-class="java.util.LinkedList">
Note that util tag has id attribute as well to refer and share with any other bean.
stateless beans: beans that are singleton and are initialized only once. The only state they have is a shared state. These beans are created while the ApplicationContext is being initialized. The SAME bean instance will be returned/injected during the lifetime of this ApplicationContext. .
stateful beans: beans that can carry state (instance variables). These are created every time an object is required.
Yes. When the second bean definition file loads, it overrides the definition from the first file. The main objective of this behavior is to ovrrride the previously loaded bean definition.
This behavior is configurable; DefaultListableBeanFactory allows to control this behavior using setAllowBeanDefinitionOverriding().
No. It is not possible.
Spring supports JSR 250 annotations that includes @PostConstruct, @PreDestroy and @Resource annotation.
@PostConstruct defines the callback method post the bean initialization.
@PreDestroy defines the method to be invoked post the bean destruction event.
@Resource wires the bean using name autowiring semantics.
primary annotation sets the bean to get preference when multiple candidates are qualified to auto-wire a single-valued dependency.
@Component public class UtilService { private UtilRepository utilRepository; @Autowired public UtilService(UtilRepository utilRepository) { this.utilRepository = utilRepository; } } @Component public class JdbcUtilRepository implements UtilRepository { public JdbcUtilService(DataSource dataSource) { // ... } } @Primary @Component public class HibernateUtilRepository implements UtilRepository { public HibernateUtilService(SessionFactory sessionFactory) { // ... } }
Using ApplicationContext.getBeansOfType method we can retrieve all the beans implementing a specific interface.
Usage: ApplicationContext.getBeansOfType(YourClass.class);
package net.javapedia.spring.beanoftype.example; import java.util.Map; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; @Configuration public class AppConfig { @Bean public Repository mongoRepository() { return new MongoRepository(); } @Bean @Primary public Repository sqlRepository() { return new SQLRepository(); } public static void main(String[] args) throws InterruptedException { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); Map<String, Repository> beansList = context.getBeansOfType(Repository.class); for (String key : beansList.keySet()) { System.out.println(key + " = " + beansList.get(key)); } } }
Complete example is here.
Spring transactions take the following properties, propagation level, isolation, timeout, rollback rules and read-only for any transaction.
Spring bean destroy method is called when the app-context is closed by calling close
method or by calling registerShutdownHook
method.
/Getting application context ApplicationContext appContext = new ClassPathXmlApplicationContext(beansXMLConfig); //cleaning context ( (ClassPathXmlApplicationContext) appContext ).close();
Singleton beans are created when the Spring container starts and are destroyed when the Spring container stops. The reason is spring container always maintains a reference to it while it is also manually referenced anywhere in your code.
Spring does only care for the creation and configuration of the prototype bean and then its the responsibility of the user (or the JVM) to do whatever is necessary.
Spring does NOT keep internal references to prototype beans.
BPP beans are a special kind of beans that get created before any other beans and interact with newly created beans.
To create a bean post processor, implement the BeanPostProcessor
interface and implement postProcessBeforeInitialization
() and postProcessAfterInitialization
() methods.
no is the default setting which means no autowiring and you should use explicit bean reference for wiring.
The quick way would be enabling the spring logging in log4j. Add spring appenders to the log4j config either log4j.xml or log4j.properties.
<category name="org.springframework.beans"> <priority value="debug" /> </category>
Based on the required module, logging could be expanded.Use either or combination as required.
<category name="org.springframework"> <priority value="debug" /> </category> <category name="org.springframework.beans"> <priority value="debug" /> </category> <category name="org.springframework.security"> <priority value="debug" /> </category>
Component Scan tells Spring the packages containing annotated classes that should be managed by Spring. If you have a class annotated with @Controller
which is in a package, if not scanned by Spring, you will not be able to use it as Spring controller.