By Sandeep Desai (http://www.thedesai.net/)
The Spring Sample shows how an Advice can be added. The springconfig2.xml file shows how to setup a before and after method advice without modifying any of the original Java code
The goal of Spring Framework is
See Rod Johnson’s Introduction to Spring Article
Inversion of Control by Martin Fowler
Spring
is a framework that aims to simplify J2EE development
You
can use all of Spring's functionality in any J2EE server, and most of it also
in non-managed environments. A central focus of Spring is to allow for reusable
business and data access objects that are not tied to specific J2EE services.
Such objects can be reused across J2EE environments (web or EJB), standalone
applications, test environments, etc without any hassle.
Spring
has a layered architecture; all its functionality builds on lower levels. So
you can e.g. use the JavaBeans configuration management without using the MVC
framework or AOP support. But if you use the web MVC framework or AOP support,
you'll find they build on the configuration framework, so you can apply your
knowledge about it immediately.
Spring uses a
setter based dependancy
injection pattern (Inversion of Control).
Spring supports
Spring runs 1500 tests
Bug fixes made by creating tests
Creating samples important part of development
Test coverage using www.cenqua.com/clover/index.html
Spring IDE for development
Spring Redistributable
Spring IoC
Dependancy Injection (better approach)
Dependancy lookup
Configuration in text property files or XML file
PropertiesBeanDefinitionReader,
XmlBeanDefinitionReader
DefaultListableBeanFactory to create beans
XmlBeanFactory
Dependancy injection
Constructor injection
Setter injection
Collection injection (Set, List, Map, Property (String
based))
Spring Books
(approx 6 books available)
Spring AOP support is dynamic. AspectJ has compile time support AOP
public class MainMuleSpringHibernate {
public static void
main(String[] args) {
String[] paths =
{"springconfig.xml"};
ApplicationContext ctx = new ClassPathXmlApplicationContext(paths);
CategoryListDAO
cdao = (CategoryListDAO) ctx.getBean("myCategoryDAO");
// fails as we
have lazy fetch on category and we are outside of session
Book book =
cdao.getBookFails("Hibernate in Action");
try {
System.out.println(book.getCategory().getName());
} catch (LazyInitializationException
e) {
System.out.println("Caught **** " + e.getMessage());
}
// works as we
have eager (join) fetch on category
book =
cdao.getBook("Hibernate in Action");
System.out.println(book.getCategory().getName()); // will work
Category c =
cdao.getCategory("Java");
if (c != null)
cdao.createBook("Thinking
in Java", c, 21, 33.27F);
}
}
DAO Example
public class CategoryListDAO extends HibernateDaoSupport {
public
CategoryListDAO() {}
public Category
getCategory(String categoryName) {
List<Category> categories = getHibernateTemplate().find("from
Category c where c.name = ?", categoryName);
if
(categories.size() > 0)
return
categories.get(0);
return null;
}
public void
createBook(String title, Category category, int inventory, float price) {
Book book = new
Book(title, category, inventory, price);
getHibernateTemplate().save(book);
}
/**
* Caller will fail
when printing book.getCategory().getName();
* with LazyInitializationException as we did not fetch Category information
* @param title
* @return
*/
public Book
getBookFails(String title) {
return (Book)
getHibernateTemplate().execute(new HibernateCallback() {
public
Object doInHibernate(Session session)
throws HibernateException, SQLException {
Criteria criteria = session.createCriteria(Book.class);
criteria.add(Expression.eq("title", "Hibernate in
Action"));
return
criteria.uniqueResult();
}
});
}
public Book
getBook(final String title) {
return (Book)
getHibernateTemplate().execute(new HibernateCallback() {
public
Object doInHibernate(Session session)
throws HibernateException, SQLException {
Criteria criteria = session.createCriteria(Book.class);
criteria.add(Expression.eq("title", "Hibernate in
Action"));
//
Fetch everything in one query instead of 2
criteria.setFetchMode("category", FetchMode.JOIN); // EAGER
Fetch
Book b = (Book)criteria.uniqueResult();
//System.out.println(b);
return
b;
}
});
}
}
SpringConfig file example
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>oracle.jdbc.driver.OracleDriver</value>
</property>
<property name="url">
<value>jdbc:oracle:thin:@localhost:1521:orcl</value>
</property>
<property name="username">
<value>scott</value>
</property>
<property name="password">
<value>tiger</value>
</property>
</bean>
<!-- Hibernate SessionFactory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref local="dataSource"/>
</property>
<property name="mappingResources">
<list>
<value>net/thedesai/mule/model/Book.hbm.xml</value>
<value>net/thedesai/mule/model/Category.hbm.xml</value>
<value>net/thedesai/mule/model/Promotion.hbm.xml</value>
<value>net/thedesai/mule/model/Customer.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<!-- Transaction manager for a single Hibernate SessionFactory (alternative to JTA) -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory"/>
</property>
</bean>
<!-- Tell Spring to setup a proxy around the DAO and do a transaction commit
after methods listed in transactionAttributes
-->
<bean id="myCategoryDAOProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="transactionManager"/>
<property name="target" ref="myCategoryDAO"/>
<property name="transactionAttributes">
<props>
<!-- intercept createBook() call and start transaction if not already started
do a commit after method over
-->
<prop key="createBook*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<bean id="myCategoryDAO" class="net.thedesai.mule.dao.CategoryListDAO">
<property name="sessionFactory">
<ref local="sessionFactory"/>
</property>
</bean>
</beans>
Spring MVC Advantages
First, a
level-set for those who don't know: Spring MVC controllers are roughly the
equivalent of Struts actions. (Spring MVC's BaseCommandController is the
closest approximation of a Struts Action.) Also, where Struts have ActionForms,
Spring has "commands". And, instead of ActionForward, Spring has
ModelAndView.
Advantage: Spring has a rich selection of Controller implementations ranging
from the simplest (the Controller interface) to the very powerful
(AbstractWizardFormController) and everything in between. You get to choose the
controller implementation that best suits your needs. In Struts, you only have
the Action class...if you need anything simpler, you are out of luck...if you
need something more powerful, you have to subclass Action and implement it
yourself.
Advantage: Spring's Controllers are much easier to test than Struts Actions.
Spring's commands are anything that extends java.lang.Object (thus easy to mock).
Struts form beans are classes that extend ActionForm (a bit harder to mock).
Disadvantage: The only disadvantage of Spring MVC over Struts is that because
Spring MVC has a very rich selection of controllers, it may be harder to
understand and know which controller to use. In fact, for a Spring newbie, the
list of controller options can be overwhelming. But, if you take a look at
Figure 8.4 in "Spring in Action", you'll see that Spring's Controller
interface is much simpler than Struts' Action and that the other
implementations progressively build upon that.
Links