Mais conteúdo relacionado
Semelhante a Spring 2.x 中文 (20)
Spring 2.x 中文
- 1. x
Spring Framework 2.0
- An Overview
- 2. 大綱
Spring Framework 簡介
Spring 2.x 新增功能
結語
2
- 3. Spring Framework的誕生
Spring之父 – R.Johnson
畢業於澳洲雪梨大學
擁有音樂學(Musicology)博士的學位
JSR-154(Servlet 2.4)規格委員
公開發表
2002年出版的專書「J2EE Design and Development」第
10章以架構描述及範例碼的形式發表。
2003年10月以開放原始碼形式釋出1.0版。
在TSS發表「Introduction to Spring Framework」文章後開
始受到Java社群重視。
3
- 5. Spring Framework 的理論基礎
為什麼要了解Spring的理論基礎?
幫助您正確評估是否採用Spring Framework
縮短學習時間
完全發揮Spring Framework 的威力
主要理論基礎
控制權倒置 (Inversion of Control)
依賴性注入 (Dependency Injection)
5
- 6. Template Method
核心概念
主流程寫在父類別
可變的部份挖空變成抽象方法
public abstract class HttpServlet … {
…
protected service(…) {
..
if(..HTTP Get..) doGet(..);
else if (..HTTP Post..) doPost(..); 主流程
..
}
public abstract void doGet(..);
public abstract void doPost(..);
? 可變邏輯
…
}
6
- 7. Template Method與Hook Method
HttpServlet
template method Service()
{
if(isHttpGet())
hook doGet()
else if(isHttpPost())
doPost()
}
hook method
doGet()
MyHttpServlet doPost()
7
- 8. 應用程式框架(Application Framework)
定義
可重用的半成品,客製化後,成為一個可用的系統
功能
提供共同領域的抽象化機制
節省開發時間
使得應用程式整體有一定的架構風格
在Template Method中,我們將主流程封裝在父類別中
內含主流程的父類別就是「框架」
透過繼承,重用主流程的子類就是「元件」,更換不同的子類別,
框架就能呈現不同的行為
8
- 10. 依賴性(Dependency)
當某類別繼承另一類別、實作另一介面或者叫用
到其它類別,我們就說此類別依賴 (depends-on)
另一個類別。
public class MySessionBean implements javax.ejb.SessionBean {
private javax.ejb.SessionContext ctx;
public void ejbCreate() {}
public void ejbRemove() {}
public void ejbActivate() {}
public void ejbPassivate() {}
public void setSessionContext(SessionContext ctx) {
this.ctx = ctx;
}
…(略)…
}
10
- 11. 依賴性對程式碼造成負面的影響
依賴性(Dependency)會對程式碼的可重用性會造
成負面影響
依賴性愈低,程式的可重用性愈高。
Liskov代換法則也可以看成是降低依賴性的手法
將Client與實作類別中間用介面隔開,去除了Client及
實作類別中間的依賴性
<<create>>
public MovieLister () {
movieFinder = new MovieFinderImpl();
}
11
- 12. 物件生成控制權的倒置 public MovieFinder create() {
…
return new MovieFinderImpl();
}
MovieFinderFactory
<<create>>
12
- 14. 輕量級容器與IoC
輕量級容器實質上是「物件生成」的控制權的倒置
輕量級容器又稱為「IoC Container」
輕量級容器中所指IoC和傳統框架型重用中的IoC意
義不同:
框架重用的IoC是「主流程主控權」的倒置
而IoC Container的IoC是「物件生成主控權」的倒置
M.Fowler建議使用依賴注入(Dependency Injection)
來指稱「物件生成主控權」的倒置,以避免概念上
的混淆
14
- 15. 小結
Template Method
Application Framework
Inversion of Control
Dependency
Dependency Injection
15
- 16. 大綱
Spring Framework簡介
Spring 2.0新增功能
Bean容器與Bean設定檔
剖面導向程式設計 (AOP)
永續性支援
Message-Driven POJO
結語
16
- 18. Bean設定檔的基本結構
Spring的Bean設定由三個部份組成:
XML宣告區段
標頭宣告區段
Bean宣告區段
DTD宣告方式
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
"http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
…
</beans>
18
- 19. (Spring 2.x) XML Schema的宣告方式
<? 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.0.xsd">
<bean id="…" class="…">
<property name="…" value="…"/>
…
</bean> 儘可能採用XML Schema形式的宣告
<bean id="…" class="…">
…
</bean>
…
</beans>
19
- 20. 設定Bean屬性
class ProductViewer {
private Product product;
…
public void setProduct(Product product) {
this.product = product;
} <bean id="productViewer" class="ProductViewer">
<property name="product">
} <ref bean="myProduct"/>
</property>
</bean>
<bean id="myProduct" class="Product">
<property name="productId" value="10001"/>
</bean>
20
- 21. Setter Injection (Spring 2.0)
class ProductViewer {
private Product product;
…
public void setProduct(Product product) {
this.product = product;
} <bean id="productViewer" class="ProductViewer">
<property name="product“ ref="myProduct“ />
} </bean>
<bean id="myProduct" class="Product">
<property name="productId" value="10001"/>
</bean>
21
- 23. 取得Bean實例 (Code)
單一設定檔
ApplicationContext context =
new ClassPathXmlApplicationContext(
“beans-config.xml”
);
Product b = (Product) context.getBean(“productB”);
多設定檔
String[] beanConfigs =
new String[]{"bean-config1.xml", "bean-config2.xml"};
ApplicationContext context =
new ClassPathXmlApplicationContext(
beanConfigs );
23
- 24. 大綱
Spring Framework簡介
Spring 2.0新增功能
Bean容器與Bean設定檔
剖面導向程式設計 (AOP)
永續性支援
Message-Driven POJO
結語
24
- 25. 商務邏輯和橫切面邏輯混雜的問題
系統開發過程中往往必須考量許
多和主要業務流程無關的橫切面
考量(Cross-Cutting Concerns)
交易(Transaction)
安全性
例外處理
記錄檔
若沒有仔細切分,容易讓程式碼
中商務流程和系統考量交雜在一
起,造成程式難以維護
25
- 26. 將剖面(Aspect)單獨考量
基於重用(Reuse)的原則,可以將這些「橫切面」的處理
邏輯抽出來成為一個「Aspect」單獨開發
開發完成後再一次套用在所有具有此需求的商務流程
商務領域考量 橫切面考量
26
- 29. (Spring 2.0) AOP命名空間的宣告
<? 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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation=
"http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/
spring-beans-2.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/
spring-aop-2.0.xsd">
…
</beans>
29
- 30. execution( modifiers-pattern?
ret-type-pattern
(Spring 2.0) AOP宣告 declaring-type-pattern?
name-pattern(param-pattern)
throws-pattern? )
<bean id="logBeforeAdvice"
class="mypackage.LogBeforeAdvice"/>
<bean id="product" class="mypackage.Product"/>
<aop:config>
<aop:aspect id="logging" ref="logBeforeAdvice">
<aop:before
pointcut="execution (* mypackage.Product.*(..))"
method="before"/>
</aop:aspect>
</aop:config>
30
- 31. (Spring 2.0) AOP Annotations
<bean id="logBeforeAdvice"
class="mypackage.LogBeforeAdvice"/>
<bean id="product" class="mypackage.Product"/>
<aop:aspectj-autoproxy/>
31
- 32. (Spring 2.0) 寫作Advice類別
@Aspect
public class LogBeforeAdvice {
…
@Before("execution(* mypackage.Product.*(..))" )
public void before(JoinPoint jointPoint) {
…(要插入的邏輯)
}
}
32
- 33. 大綱
Spring Framework簡介
Spring 2.0新增功能
Bean容器與Bean設定檔
剖面導向程式設計 (AOP)
永續性與交易支援
Message-Driven POJO
結語
33
- 34. (Spring 2.0) 使用tx標籤進行宣告式交易
Transaction
Manager
execution(* *.ProductDao.*(..)) <tx:advice>
Transaction Attribute= Require
Isolation Level= Default
productDao
execution( modifiers-pattern?
ret-type-pattern
declaring-type-pattern?
name-pattern(param-pattern)
34 throws-pattern? )
- 35. 使用tx標籤進行宣告式交易
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="get*" read-only="true" />
<tx:method name="*"
propagation="REQUIRED"
isolation="DEFAULT"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:advisor pointcut="execution(* *.ProductDao.*(..))"
advice-ref="txAdvice" />
</aop:config>
35
- 36. (Spring 2.0)
使用@Transactional進行宣告式交易
<tx:annotation-driven transaction-manager="txManager" />
// 直接標記在介面的實作成品上
public class ProductDaoJdbcImpl
extends JdbcDaoSupport implements ProductDao
{
@Transactional(readOnly = true)
public List getProducts(){
…(存取資料)
}
@Transactional(readOnly = false,
propagation = Propagation.REQUIRED,
isolation = Isolation.DEFAULT)
public void save(Product product){
…(存取資料)
}
}
36
- 37. Hibernate與JPA
開發人員可以選擇只使用JPA以確
保最大的相容性,或者透過
Hibernate API實作更進階的功能,
甚至也可以將二者混合使用!
Java Persistence API Hibernate API
Hibernate Annotation (JPA) Hibernate Annotation (Hibernate)
Hibernate EntityManager Hibernate XML 對映檔
Hibernate Core
37
- 38. Spring對Hibernate的封裝
HibernateTemplate
hibernate.cfg.xml
Configuration Criteria Query
persist()
save()
update()
SessionFactory Session saveOrUpdate()
delete()
Transaction
38 SessionFactoryBean
- 39. (Spring 2.0) 使用JPA Annotations
@Entity
@Table(name = "TB_PRODUCT")
public class Product {
@Id
@GeneratedValue(strategy=GenerationType.TABLE)
@Column(name = "id")
private int productId;
@Column(name = "name") TB_PRODUCT:
private String name; 名稱 主鍵 型別
id Yes Integer
@Column(name = "price")
name No varchar
private int price;
price No Integer
…(以上三個私有欄位的getter methods及setter methods)…
}
39
- 40. Spring-Hibernate-DAO整合策略
相依性注入
SessionFactoryBean HibernateTemplate
HibernateDaoSupport
ProductDao
ProductDaoHibernateImpl
實作(implements) 繼承(extends)
40
- 41. Spring-Hibernate整合
public class ProductDaoHibernateImpl extends HibernateDaoSupport
implements ProductDao {
public void save(Product product)
{
getHibernateTemplate().save(product);
}
public List getProducts() throws DataAccessException
{
return (List) getHibernateTemplate().execute( new HibernateCallback() {
public Object doInHibernate(Session session) throws
HibernateException {
Criteria criteria = session.createCriteria(Product.class);
criteria.addOrder(Order.asc("price"));
return criteria.list();
}
41 });
}// end getProducts
- 42. SessionFactoryBean (Annotation)
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.
annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>Product</value>
</list>
</property>
<property name="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.show_sql=true
</value>
</property>
</bean>
42
- 44. 大綱
Spring Framework簡介
Spring 2.0新增功能
Bean容器與Bean設定檔
剖面導向程式設計 (AOP)
永續性支援
Message-Driven POJO
結語
44
- 45. (Spring 2.0) Message-Driven POJO
public class MyMessageDrivenPojo implements MessageListener
{
public void onMessage(Message message){
… // 處理所收到的處理訊息
}
}
主程式
public static void main(String[] args) {
DefaultMessageListenerContainer container =
(DefaultMessageListenerContainer)
context.getBean("listenerContainer");
container.start();
}
45
- 46. Message-Driven POJO (MDP)
<bean id="myMDP" class="MyMessageDrivenPojo" />
<bean id="listenerContainer“
class="org.springframework.jms.listener.
DefaultMessageListenerContainer">
<property name="concurrentConsumers" value="2" />
<property name="connectionFactory" ref="jmsFactory" />
<property name="destination" ref="destination" />
<property name="messageListener" ref="myMDP" />
</bean>
46
- 47. 加入交易支援
<bean id="txManager" class="org.springframework.jms.connection.
JmsTransactionManager">
<property name="connectionFactory" ref="connectionFactory" />
</bean>
<bean
id="listenerContainer“ class="org.springframework.jms.listener.
DefaultMessageListenerContainer">
<property name="concurrentConsumers" value="2" />
<property name="connectionFactory" ref="jmsFactory" />
<property name="destination" ref="destination" />
<property name="messageListener" ref="myMDP" />
<property name="transactionManager" ref=“txManager" />
</bean>
47
- 48. 結語
Spring 2.0 是一個全方位的應用程式框架,主要
功能包含了:
輕量級容器
實現依賴注入(Dependency Injection)及非侵入性(No
intrusive)的框架
提供AOP(Aspect-oriented programming)機制
提供對持久層(Persistence)、交易(Transaction)的支援
提供MVC Web框架的實現
對於其它常用企業服務API提供一致的模型封裝
48
- 50. 小結: Spring Framework的設計理念
透過介面進行系統設計(Programming by interface)
以傳統Java物件為主 (POJO-based Programming)
非侵入性
一致的設定檔格式
50
- 51. 依賴注入的型式
三種型式
從setter方法注入資源的Setter Injection
從建構子(Constructor)注入的Constructor Injection
透過介面(Interface)注入的Interface injection
Spring Framework支援Setter Injection與
Constructor Injection
透過介面的相依性注入具有較強的侵入性,所以Spring
並未採用。
51
- 53. 去除Glue Code
MovieServlet MovieService IoCManagerServlet
IoC Container
53
- 54. AOP觀念與術語
Aspect
代表一個Cross-Cutting Concerns
由Pointcut與Advice二類的元件所組成
Advice是Aspect的「具體實作」
Join Points
Advice在切入商務流程的「點」稱之為Join Point
就實作面來說,就是Advice在應用程式中被執行的時間點
Spring只支援類別方法的Join Points
Spring不支援Field成員的Join Points,Spring設計人員認為支援
Field的Join Points會破壞物件的封裝性
54
- 55. AOP觀念與術語(2)
Pointcut
Pointcut用來定義一群Join Points
當呼叫的方法符合Pointcut表示式時,系統會自動將Advice與方法
縫合(Weaving)
55
- 56. Hibernate的宣告式交易
一般區域交易
<bean id="txManager"
class="org.springframework.jdbc.datasource.
DataSourceTransactionManager">
<property name="dataSource" ref="myDataSource" />
</bean>
Hibernate宣告式交易
<bean id="txManager"
class="org.springframework.orm.hibernate3.
HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
56
- 57. NamedParameterJdbcTemplate
String sql = "INSERT INTO t_user (name,age)
VALUES(:userName, :userAge)";
Map namedParameters = new HashMap();
namedParameters.put("userName", name);
namedParameters.put("userAge", age);
NamedParameterJdbcTemplate jdbcTemplate =
new NamedParameterJdbcTemplate(dataSource);
List rows = jdbcTemplate.queryForList(sql, namedParameters);
57
- 58. SimpleJdbcTemplate
JDK 5.0以上適用,支援泛型
String sql = "SELECT * FROM user WHERE id=?";
ParameterizedRowMapper<User> mapper =
new ParameterizedRowMapper<User>() {
public User mapRow(ResultSet rs, int rowNum)
throws SQLException {
…
return user;
}
};
SimpleJdbcTemplate jdbcTemplate = new SimpleJdbcTemplate(dataSource);
jdbcTemplate.queryForObject(sql, mapper, id);
58
- 59. MessageListenerAdapter
上面例子中的MyMessageDrivenPojo 仍然具有相依性
必須繼承javax.jms.MessageListener介面
MessageListenerAdapter
完全切除MDP與JMS的依賴關係
假設使用者自行定義了訊息的處理介面
將介面傳入Adapter做為建構子的參數
public interface MyMessageHandler {
void processMessage(String message);
} 不需要實作MessageListener! 實作
Public class MyMessageHandlerImpl
implements MyMessageHandler { …}
59
- 60. MessageListenerAdapter – 設定檔
<bean id="messageListenerAdapter" class="org.springframework.jms.listener.
adapter.MessageListenerAdapter">
<constructor-arg>
<bean class="MyMessageHandlerImpl"/>
</constructor-arg>
<property name="defaultListenerMethod“ value="processMessage"/>
</bean>
<bean id="listenerContainer“ class="org.springframework.jms.listener.
DefaultMessageListenerContainer">
<property name="concurrentConsumers" value="2" />
<property name="connectionFactory" ref="jmsFactory" />
<property name="destination" ref="destination" />
<property name="messageListener" ref="messageListenerAdapter " />
</bean>
60