More Related Content Similar to Spring 2.x 中文 (20) More from Guo Albert (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