一、开始spring之旅
Spring是一个开源的控制反转(Inversion of Control ,IoC)和面向切面(AOP)的容器框架.它的主要目得是简化企业开发.
public class PersonServiceBean { private PersonDao personDao = new PersonDaoBean(); public void save(Person person){ personDao.save(person); } }
PersonDaoBean 是在应用内部创建及维护的。所谓控制反转就是应用本身不负责依赖对象的创建及维护,依赖对象的创建及维护是由外部容器负责的。这样控制权就由应用转移到了外部容器,控制权的转移就是所谓反转。
依赖注入(Dependency Injection)
当我们把依赖对象交给外部容器负责创建,那么PersonServiceBean 类可以改成如下:
public class PersonServiceBean { private PersonDao personDao ; //通过构造器参数,让容器把创建好的依赖对象注入进PersonServiceBean,当然也可以使用setter方法进行注入。 public PersonServiceBean(PersonDao personDao){ this.personDao=personDao; } public void save(Person person){ personDao.save(person); } }
所谓依赖注入就是指:在运行期,由外部容器动态地将依赖对象注入到组件中。
为何要使用Spring
至少在我看来,在项目中引入spring立即可以带来下面的好处
1.降低组件之间的耦合度,实现软件各层之间的解耦。
2.可以使用容器提供的众多服务,如:事务管理服务、消息服务等等。当我们使用容器管理事务时,开发人员就不再需要手工控制事务.也不需处理复杂的事务传播。
3.容器提供单例模式支持,开发人员不再需要自己编写实现代码。
4.容器提供了AOP技术,利用它很容易实现如权限拦截、运行期监控等功能。
5.容器提供的众多辅作类,使用这些类能够加快应用的开发,如: JdbcTemplate、 HibernateTemplate。
6.Spring对于主流的应用框架提供了集成支持,如:集成Hibernate、JPA、Struts等,这样更便于应用的开发。
如果使用Spring, 我们就不再需要手工控制事务
另外,如果使用spring, 我们也不需要处理复杂的事务传播行为
public void payment(){ Bean1.update();//更新金额 Bean2.save();//记录操作日志 }如果我们不使用Spring,针对下面这两种业务需求,我们该如何做?
第1种可能的业务需求:要求Bean1.update()和Bean2.save()在同一个事务中执行。
第2种可能的业务需求:要求不管Bean1.update() 的事务是否成功,都需要记录操作日志
public class Bean1 { public void update(){//注意:下面省略了一些代码 Connection conn = null; conn.setAutoCommit(false); Statement.executeUpdate(“update account set amount=? where id=?"); } } public class Bean2 { public void save(){//注意:下面省略了一些代码 Connection conn = null; conn.setAutoCommit(false); Statement.executeUpdate(“insert into Log (content) values (?)"); } }使用Spring,不再需要我们处理复杂的事务传播行为
使用Spring,我们只需要通过声明式的事务属性配置就可以轻松地实现这两种业务需求
1.要求Bean1.update()和Bean2.save()的在同一个事务中执行
2.要求不管Bean1.update() 的事务是否成功,都需要记录日志。
@Transactional(propagation=Propagation.Required) public void payment(){ Bean1.update();//更新金额 Bean2.save();//记录日志 } public class Bean1 { @Transactional(propagation=Propagation.Required) public void update(){ executeUpdate(“update account set amount=? where id=?"); } } public class Bean2 { @Transactional(propagation=Propagation.RequiresNew) public void save(){ executeUpdate(“insert into Log (content) values (?)"); } }spring的配置文件模版
<?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-2.5.xsd"> ..... </beans>
该配置模版可以从spring的参考手册或spring的例子中得到。配置文件的取名可以任意,文件可以存放在任何目录下,但考虑到通用性,一般放在类路径下。
一、知识点
静态工厂方法的目的是在静态方法中封装对象的创建过程。请求一个对象的客户只要调用这个方法,不需要了解创建的细节。
Spring支持调用一个静态工厂方法创建Bean,这个工厂方法应该在factory-method属性中指定。
二、代码示例
抽象产品类Product
/* * Copyright 2013-2015 */ package com.jackie.codeproject.springrecipesnote.springadvancedioc; /** * Title: Product.java * 产品抽象类 * * @author jackie * @since Apr 14, 2013 8:09:49 PM * @version V1.0 */ public abstract class Product { private String name; private double price; public Product() { } /** * <p>Title: </p> * <p>含参构造函数</p> * @param name * @param price */ public Product(String name, double price) { this.name = name; this.price = price; } /** * @return the name */ public String getName() { return name; } /** * @param name the name to set */ public void setName(String name) { this.name = name; } /** * @return the price */ public double getPrice() { return price; } /** * @param price the price to set */ public void setPrice(double price) { this.price = price; } public String toString() { return name + " " + price; } }Battery和Disc继承Product
/* * Copyright 2013-2015 */ package com.jackie.codeproject.springrecipesnote.springadvancedioc; /** * Title: Battery.java 类的功能说明 * * @author jackie * @since Apr 14, 2013 8:14:26 PM * @version V1.0 */ public class Battery extends Product { private boolean rechargeable; public Battery() { super(); } public Battery(String name, double price) { super(name, price); } /** * @return the rechargeable */ public boolean isRechargeable() { return rechargeable; } /** * @param rechargeable * the rechargeable to set */ public void setRechargeable(boolean rechargeable) { this.rechargeable = rechargeable; } }
/* * Copyright 2013-2015 */ package com.jackie.codeproject.springrecipesnote.springadvancedioc; /** * Title: Disc.java 类的功能说明 * * @author jackie * @since Apr 14, 2013 8:18:30 PM * @version V1.0 */ public class Disc extends Product { private int capacity; public Disc() { super(); } public Disc(String name, double price) { super(name, price); } /** * @return the capacity */ public int getCapacity() { return capacity; } /** * @param capacity * the capacity to set */ public void setCapacity(int capacity) { this.capacity = capacity; } }工厂类ProductCreator
/* * Copyright 2013-2015 */ package com.jackie.codeproject.springrecipesnote.springadvancedioc; /** * Title: ProductCreator.java * 工厂类 * * @author jackie * @since Apr 23, 2013 8:37:50 PM * @version V1.0 */ public class ProductCreator { public static Product createProduct(String productId) { if ("aaa".equals(productId)) { return new Battery("AAA", 2.5); } else if ("cdrw".equals(productId)) { return new Disc("CD-RW", 1.5); } throw new IllegalArgumentException("Unknown product"); } }声明一个静态工厂方法创建的Bean,需要在class属性中指定工厂类,在factory-method属性中指定工厂方法名称。最后,使用<constructor-arg>元素传递方法的参数。
<?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.2.xsd"> <bean id="aaa" class="com.jackie.codeproject.springrecipesnote.springadvancedioc.ProductCreator" factory-method="createProduct"> <constructor-arg value="aaa" /> </bean> <bean id="cdrw" class="com.jackie.codeproject.springrecipesnote.springadvancedioc.ProductCreator" factory-method="createProduct"> <constructor-arg value="cdrw" /> </bean> </beans>如果工厂方法抛出任何异常,Spring将用BeanCreationException对其进行封装。
前述的Bean配置和如下代码片段等价:
Product aaa = ProductCreator.createProduct("aaa"); Product cdrw= ProductCreator.createProduct("cdrw");
一、什么是Spring?
Spring是一个开源的控制反转(Inversion of Control ,IoC)和面向切面(AOP)的容器框架.它的主要目得是简化企业开发.
二、PersonDaoBean 是在应用内部创建及维护的。所谓控制反转就是应用本身不负责依赖对象的创建及维护,依赖对象的创建及维护是由外部容器负责的。这样控制权就由应用转移到了外部容器,控制权的转移就是所谓反转。
三、依赖注入(Dependency Injection)
当我们把依赖对象交给外部容器负责创建,那么PersonServiceBean 类可以改成如下:
public class PersonServiceBean {
private PersonDao personDao ;
//通过构造器参数,让容器把创建好的依赖对象注入进PersonServiceBean,当然也可以使用setter方法进行注入。
public PersonServiceBean(PersonDao personDao){
this.personDao=personDao;
}
public void save(Person person){
personDao.save(person);
}
}
所谓依赖注入就是指:在运行期,由外部容器动态地将依赖对象注入到组件中。
四、为何要使用Spring
至少在我看来,在项目中引入spring立即可以带来下面的好处
降低组件之间的耦合度,实现软件各层之间的解耦。
可以使用容器提供的众多服务,如:事务管理服务、消息服务等等。当我们使用容器管理事务时,开发人员就不再需要手工控制事务.也不需处理复杂的事务传播。
容器提供单例模式支持,开发人员不再需要自己编写实现代码。
容器提供了AOP技术,利用它很容易实现如权限拦截、运行期监控等功能。
容器提供的众多辅作类,使用这些类能够加快应用的开发,如: JdbcTemplate、 HibernateTemplate。
Spring对于主流的应用框架提供了集成支持,如:集成Hibernate、JPA、Struts等,这样更便于应用的开发。
另外,如果使用spring, 我们也不需要处理复杂的事务传播行为
public void payment(){
Bean1.update();//更新金额
Bean2.save();//记录操作日志
}
如果我们不使用Spring,针对下面这两种业务需求,我们该如何做?
第1种可能的业务需求:要求Bean1.update()和Bean2.save()在同一个事务中执行。
第2种可能的业务需求:要求不管Bean1.update() 的事务是否成功,都需要记录操作日志。
public class Bean1 {
public void update(){//注意:下面省略了一些代码
Connection conn = null;
conn.setAutoCommit(false);
Statement.executeUpdate(“update account set amount=? where id=?");
}
}
public class Bean2 {
public void save(){//注意:下面省略了一些代码
Connection conn = null;
conn.setAutoCommit(false);
Statement.executeUpdate(“insert into Log (content) values (?)");
}
}
3/使用Spring,不再需要我们处理复杂的事务传播行为
使用Spring,我们只需要通过声明式的事务属性配置就可以轻松地实现这两种业务需求
1.要求Bean1.update()和Bean2.save()的在同一个事务中执行
2.要求不管Bean1.update() 的事务是否成功,都需要记录日志。
@Transactional(propagation=Propagation.Required)
public void payment(){
Bean1.update();//更新金额
Bean2.save();//记录日志
}
public class Bean1 {
@Transactional(propagation=Propagation.Required)
public void update(){
executeUpdate(“update account set amount=? where id=?");
}
}
public class Bean2 {
@Transactional(propagation=Propagation.RequiresNew)
public void save(){
executeUpdate(“insert into Log (content) values (?)");
}
}