#Benefits of the POJO Programming model
The most important advantage of the POJO programming model is that coding application classes is very fast and simple. This is because classes don’t need to depend on any particular API, implement any special interface, or extend from a particular framework class. You do not have to create any special callback methods until you really need them.
Because the POJO‐based classes don’t depend on any particular API or framework code, they can easily be transferred over the network and used between layers. Therefore, you don’t need to create separate data transfer object classes in order to carry data over the network.
You don’t need to deploy your classes into any container or wait for long deployment cycles so that you can run and test them. You can easily test your classes within your favorite IDE using JUnit. You don’t need to employ in‐container testing frameworks like Cactus to perform integration unit tests.
The POJO programming model lets you code with an object‐oriented perspective instead of a pro- cedural style. It becomes possible to reflect the problem domain exactly to the solution domain. Business logic can be handled over a more fine‐grained model, which is also richer in terms of behavioral aspects.
#Dependency Injection with Spring
The lifetimes of Spring‐managed beans can be different according to their scope definitions. This chapter lists the scopes supported by the Spring Container and explains how different scopes behave in the system. You can create Spring beans either during startup (eager initialization), or delay their creation until they are needed in the system (lazy initialization). In this chapter you find out how those bean initialization methods work, the pros and cons of each, and the different bean instantia- tion methods provided by the Spring Container.
#Spring ioC Container
The core of the Spring Application Framework is its Inversion of Control (IoC) Container. Its job is to instantiate, initialize, and wire up objects of the application, as well as provide lots of other features available in Spring throughout an object's lifetime. The objects that form the backbone of your appli- cation, and are managed by Spring Container, are called beans. They are ordinary Java objects—also known as POJOs—but they are instantiated, assembled by the Spring Container, and managed within it.
#Configuration Metadata
The Spring Container expects information from you to instantiate beans and to specify how to wire them together. This information is called configuration metadata. Together with this configuration metadata, the Spring Container takes classes written in the application and then creates and assem- bles beans in it.
###Configuration Metadata options
- XML
- Annotation-based
- Java-based
#Dependency Injection
dependency injection as moving the creation of dependent components out of code and managing them within an IoC Container. two types of dependency injection, methods—setter injection and constructor injection
###Setter Injection
Setter injection is performed after a bean instance is created. All properties defined in the configura- tion metadata of the bean are injected by calling setter methods corresponding to those properties. It is possible to inject other bean dependencies and primitive values, strings, classes, enums, and so on.
<bean id="accountService" class="com.wiley.beginningspring.ch2.AccountServiceImpl">
<property name="accountDao" ref="accountDao"/>
</bean>
The AccountService bean needs a bean with the type AccountDao. Therefore we specified the accountDao bean name in the ref attribute. If there is no bean with the accountDao name in the con- tainer, the bootstrap process fails
To inject dependency values other than bean references, like int, Boolean, String, Enum, and so on, you can use the value attribute of the element as shown here:
<bean id="account1" class="com.wiley.beginningspring.ch2.Account">
<property name="id" value="1" />
<property name="ownerName" value="John" />
<property name="balance" value="10.0"/>
<property name="locked" value="false" />
</bean>
The following code snippet shows how a Map typed property can be populated. Similar to a element, you can use the , , or elements to populate Collection typed prop- erties
#Constructor Injection
Constructor injection is performed during component creation. Dependencies are expressed as con- structor arguments, and the container identifies which constructor to invoke by looking at types of those constructor arguments specified in the bean definition. The following Try It Out shows how Spring beans can be configured using constructor injection.
<?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.xsd">
<bean id="accountService" class="com.omeroot...AccountServiceImpl">
<contructor-arg ref="accountDao" ref="accountDao" />
</bean>
<bean id="accountDao" class="com.omeroot.....AccountDao">
</bean>
</beans>
#Autowiring
You don't have to explicitly define dependencies in your bean definitions; you can let the Spring Container inject them to your beans automatically. This is called autowiring. It is useful espe- cially during development because bean definitions need to be updated as the codebase evolves. Autowiring has three modes: byType, byName, and constructor.
<bean id="accountService" class="com.wiley.beginningspring.ch2.AccountServiceImpl" autowire="byType"/>
<bean id="accountDao" class="com.wiley.beginningspring.ch2.↵ AccountDaoInMemoryImpl"/>
If more than one bean instance autowiring candidates are suitable for injection to a specific prop- erty, dependency injection fails. One way is to exclude other beans from autowiring candidates:
<bean id="accountService" class="com.wiley.beginningspring.ch2.AccountServiceImpl" autowire="byType"/>
<bean id="accountDao" class="com.wiley.beginningspring.ch2.AccountDaoInMemoryImpl" autowire-candidate="false"/>
<bean id="accountDaoJdbc" class="com.wiley.beginningspring.ch2.AccountDaoJdbcImpl"/>
#Bean Instantiation Methods
public class Foo {
private String name;
public Foo() { }
public Foo(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
<bean id="foo1" class="com.wiley.beginningspring.ch2.Foo">
<property name="name" value="foo1"/>
</bean>
<bean id="foo2" class="com.wiley.beginningspring.ch2.Foo">
<constructor-arg value="foo2"/>
</bean>
The second option for creating beans is to invoke the static or instance factory methods that are available. For example, the FooFactory class has two factory methods in the following code snip- pet. The createFoo3() method has a static modifier. Therefore, it can be invoked without having a FooFactory instance available at run time. The second factory method, createFoo4(), has no static modifier. Therefore, it can only be invoked if there is an instance of FooFactory available at run time:
###Auto Scanning Component
package com.dmomer.dao
import org.springframework.stereotype.Component;
@Component
public class CustomerDAO
{
@Override
public String toString() {
return "Hello , This is CustomerDAO";
}
}
//service scope
package com.dmomer.service
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.mkyong.customer.dao.CustomerDAO;
@Component
public class CustomerService
{
@Autowired
CustomerDAO customerDAO;
@Override
public String toString() {
return "CustomerService [customerDAO=" + customerDAO + "]";
}
}
//xml scope
<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.dmomer" />
</beans>
#####Annotation Types
- @Component
- @Repository
- @Service
- @Controller
#Bean Scopes
The lifetime of beans created by the Spring Container is called bean scope. By default, all beans cre- ated by the Spring Container have singleton scope. In other words, only one bean instance is created for a bean definition, and that instance is used by the container for the whole application lifetime. This scope is very appropriate for beans that correspond to layers such as controller, service, and data access object (DAO). They are usually stateless instances that serve several different requests at the same time:
<bean id="commandManager" class="com.wiley.beginningspring.ch2.CommandManager" scope="singleton">
</bean>
You can use the scope attribute of the element to specify the scope of a bean definition. Because its value is singleton by default, you don't need to use it for singleton‐scoped beans.
The second scope supported by Spring is prototype. It is very similar to creating an object using the new operator in Java code. Beans with the prototype scope are created whenever they are accessed in the container, either from other bean definitions via bean reference, or from within the application code with explicit bean lookup using the ApplicationContext.getBean() method:
<bean id="command" class="com.wiley.beginningspring.ch2.Command" scope="prototype"> </bean>
They can only be used in web applications. Attempting to use them in a standalone application causes the Spring Container not to bootstrap. A request‐scoped bean is created every time a new web request arrives at the application, and that same bean instance is used throughout the request. A session‐scoped bean, as you may have already guessed, is created each time a new HTTP Session is created, and that instance stays alive as the session stays alive.
<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/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userPreferences" class="com.wiley.beginningspring.ch2.~CA UserPreferences">
<aop:scoped-proxy/>
</bean>
</beans>
When you define request‐ and session‐scoped beans, you have to place the aop:scoped‐proxy/ element as a child element in the element. aop:scoped‐proxy is available in the aspect oriented programming (AOP) namespace, and you can see how that namespace is activated in the earlier XML snippet. This directive causes the Spring Container to generate a class extend- ing from the bean definition class dynamically at run time, and a proxy object is created using that dynamically generated class. The proxy object is then injected to other beans referencing the scoped bean in the container. At run time, when a method call arrives to that proxy object, Spring tries to obtain a real target bean instance in the current request or session. If there is an existing bean, it is used to handle method invocation. Otherwise, a new instance is created and used for that request or session.
#Lazy Initialization
The Spring Container, by default, creates beans during its startup. This is called eager bean initialization. Its advantage is that you can see configuration errors as early as possible. For example, in XML‐based configuration you may have had a typo in the class attribute of a bean definition, or you may refer to an unavailable bean definition. On the other hand, it may slow down the bootstrap process if you have lots of bean definitions or some special beans, such as Hibernate SessionFactory or JPA EntityManagerFactory, whose initialization may take a considerable amount of time. Some beans may only be required for specific use cases or alternative scenarios, and are not needed for other times. In such cases, eager initialization may result in unnecessary heap memory consumption as well.
Spring also supports lazy bean initialization. If beans are configured by developers to be created lazily, the container delays their creation until they are really needed. Their creation is triggered either by a reference made from another bean that is already being created or by an explicit bean lookup performed from within application code.
In XML‐based configuration, you can use the lazy‐init attribute in the element to define a bean as lazy. To define all beans as lazy in an XML file, you can use the default‐lazy‐init attri- bute of the element. Lazy behavior defined on the XML file level can be overridden on the bean definition level as well.
<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.xsd" default-lazy-init="true">
<bean id="accountService" class="com.wiley.beginningspring.ch2.~CA AccountServiceImpl">
<property name="accountDao" ref="accountDao"/>
</bean>
<bean id="accountDao" class="com.wiley.beginningspring.ch2.~CA AccountDaoInMemoryImpl" lazy-init="false">
</bean>
</beans>
In annotation‐ and Java‐based configuration, you can use the org.springframework.context .annotation.Lazy annotation to enable lazy behavior. If the @Lazy attribute with a value of true is present on the class level together with the @Component annotation, or on the factory method level with the @Bean annotation, that bean definition is lazy:
@Service("accountService")
@Lazy(true)
public class AccountServiceImpl implements AccountService {
//...
}
The advantage of lazy bean creation is that it speeds container bootstrap time and has a smaller memory footprint. On the other hand, if bean configuration errors exist in the metadata, they may remain unnoticed until their scenarios are tested.
Take care while you are defining beans as lazy. If one of their depending beans, either directly or indirectly, is defined as eager, your lazy definition won't have any effect. Eager bean definition is processed during startup, so it triggers processing lazy bean definition as well.
#Life-Cycle Callbacks
Beans can define callback methods, which can be invoked by the container at specific points during their lifetime. Those points are after their instantiation and just before termination of their defined scopes. They are also called init and destroy methods. You have several different ways to define and invoke such life-cycle callback methods. XML‐based configuration elements have init‐method and destroy‐method attributes that accept method names in the bean class as attribute values:
public class Foo {
public void init() {
System.out.println("init method is called");
}
public void destroy() {
System.out.println("destroy method is called");
}
}
<bean id="foo" class="com.wiley.beginningspring.ch2.Foo" init-method="init" destroy-method="destroy"/>
The init method is invoked by the container after the bean is created, and its properties are injected. Because the bean instance is ready to use, you can perform anything within the init method in which the bean's properties are involved. The destroy method is invoked just before the end of a bean's lifetime. Because the lifetime of beans is changeable according to their scopes, the invocation of destroy methods may be occur at different times. For example, the destroy methods of singleton‐ scoped beans are invoked at the shutdown of the whole Spring Container. The destroy methods of request‐scoped beans are invoked at the end of the current web request, and the destroy methods of session‐scoped beans are invoked at HTTP session timeout or invalidation. Prototype‐scoped beans, on the other hand, are not tracked after their instantiation; therefore, their destroy methods cannot be invoked. Method names can be anything. There is no restriction; however, methods should return void and accept nothing as input arguments. They can throw any type of exception.
public class Bar {
@PostConstruct
public void init() throws Exception {
System.out.println("init method is called");
}
@PreDestroy
public void destroy() throws RuntimeException {
System.out.println("destroy method is called");
}
}
<bean class="com.wiley.beginningspring.ch2.Bar"/> <context:annotation-config/>
#Bean Definition Profiles
Sometimes you need to define beans according to the runtime environment. For example, you may use different databases for development and production environments. During development, you may prefer to use a lightweight, possibly in‐memory database, such as H2, to quickly test your codebase. In a production environment, on the other hand, you may prefer a more enterprise‐level product, such as Oracle, DB2, or MySQL. In some other related case, you may define your own javax.sql.DataSource‐typed bean for the development environment, or you may prefer to access the DataSource object managed by the application server that provides some connection pooling capabilities. Prior to Spring 3.1, you had to handle such platform‐ or environment‐specific bean defi- nition issues as discussed next.
Because you can't have two bean definitions with the same name in a single configuration meta- data file, you had to first create two different bean configuration metadata files in which your bean definitions for that specific environment or platform should exist. For example, you would create a dataSource‐dev.xml file with a dataSource bean definition that provides JDBC connections to a lightweight, in‐memory H2 database:
<?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.xsd">
<bean id="dataSource" class="org.springframework.jdbc.datasource.SingleConnectionDataSource">
<property name="driverClassName" value="org.h2.Driver"/> <property name="url" value="jdbc:h2:mem:test"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
</beans>
For a production environment, you might have had another file called dataSource‐prod.xml in which another dataSource bean was defined. But this time, instead of being created by the applica- tion, it was obtained from the application server's JDBC context through JNDI lookup:
<?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.xsd">
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/DS"/>
</bean>
</beans>
At this point, you need one of those two dataSource bean definitions selectively to be processed according to the target runtime environment. If, for example, the target runtime environment is development or test, the dataSource‐dev.xml file should be loaded by the container; otherwise, dataSource‐prod.xml should be loaded. For this purpose, you usually created a third bean con- figuration file with an import element that imports one of those two configuration metadata sources according to the value of some platform‐specific value:
<?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-4.0.xsd">
<context:property-placeholder/>
<import resource="classpath:/dataSource-${targetPlatform}.xml"/>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
In the preceding code snippet, the ${targetPlatform} placeholder is resolved either from the operating system's environment variables or from JVM's system properties (for example, it can be specified as the ‐DtargetPlatform=dev JVM argument). In either case, if it exists, the place- holder is replaced with the value, and the configuration metadata file is resolved according to that value.
Bean definition profiles were introduced in Spring 3.1. In XML‐based configuration, profile support enables having a element within another element:
<?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.xsd">
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<beans profile="dev,test">
<bean id="dataSource"
class="org.springframework.jdbc.datasource.SingleConnectionDataSource"> <property name="driverClassName" value="org.h2.Driver" />
<property name="url" value="jdbc:h2:mem:test" />
<property name="username" value="sa" />
<property name="password" value="" />
</bean>
</beans>
<beans profile="prod">
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/DS" /> </bean>
</beans>
</beans>
