Upload
guo-albert
View
2.170
Download
0
Embed Size (px)
Citation preview
Spring Framework 2.0- An Overview
x
2
大綱
Spring Framework 簡介
Spring 2.x 新增功能
結語
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社群重視。
4
Spring Framework架構概觀
5
Spring Framework 的理論基礎
為什麼要了解Spring的理論基礎?
幫助您正確評估是否採用Spring Framework
縮短學習時間
完全發揮Spring Framework 的威力
主要理論基礎
控制權倒置 (Inversion of Control)
依賴性注入 (Dependency Injection)
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(..);
…
}
?
主流程
可變邏輯
7
Template Method與Hook Method
Service()
{
if(isHttpGet())
doGet()
else if(isHttpPost())
doPost()
}
HttpServlet
hook method
template method
hook
doGet()
doPost()MyHttpServlet
8
應用程式框架(Application Framework)
定義
可重用的半成品,客製化後,成為一個可用的系統
功能
提供共同領域的抽象化機制
節省開發時間
使得應用程式整體有一定的架構風格
在Template Method中,我們將主流程封裝在父類別中
內含主流程的父類別就是「框架」
透過繼承,重用主流程的子類就是「元件」,更換不同的子類別,框架就能呈現不同的行為
9
Inversion Of Control (IoC)
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;
}
…(略)…
}
11
依賴性對程式碼造成負面的影響
依賴性(Dependency)會對程式碼的可重用性會造成負面影響
依賴性愈低,程式的可重用性愈高。
Liskov代換法則也可以看成是降低依賴性的手法
將Client與實作類別中間用介面隔開,去除了Client及實作類別中間的依賴性
<<create>>public MovieLister () {
movieFinder = new MovieFinderImpl();
}
12
物件生成控制權的倒置
<<create>>
MovieFinderFactory
public MovieFinder create() {
…
return new MovieFinderImpl();
}
13
Dependency Injection
IoC Container
14
輕量級容器與IoC
輕量級容器實質上是「物件生成」的控制權的倒置
輕量級容器又稱為「IoC Container」
輕量級容器中所指IoC和傳統框架型重用中的IoC意義不同:
框架重用的IoC是「主流程主控權」的倒置
而IoC Container的IoC是「物件生成主控權」的倒置
M.Fowler建議使用依賴注入(Dependency Injection)
來指稱「物件生成主控權」的倒置,以避免概念上的混淆
15
小結
Template Method
Application Framework
Inversion of Control
Dependency
Dependency Injection
16
大綱
Spring Framework簡介
Spring 2.0新增功能
Bean容器與Bean設定檔
剖面導向程式設計 (AOP)
永續性支援
Message-Driven POJO
結語
17
Bean 容器
Bean 設定檔POJO
客戶端
Bean 容器運作模式
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>
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>
<bean id="…" class="…">
…
</bean>
…
</beans>
儘可能採用XML Schema形式的宣告
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>
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>
22
(Spring 2.x) p-namespace的簡便語法
<bean id="myProduct" class="Product">
<property name="productId“ value="10001"/>
<property name=“myName" ref=“anotherBean"/>
</bean>
<bean id="myProduct" class="Product"
p:productId="10001"
p:myName-ref=“anotherBean"
/>
在標頭加上「xmlns:p=http://www.springframework.org/schema/p」即可使用 p-namespace的簡便語法
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 );
24
大綱
Spring Framework簡介
Spring 2.0新增功能
Bean容器與Bean設定檔
剖面導向程式設計 (AOP)
永續性支援
Message-Driven POJO
結語
25
商務邏輯和橫切面邏輯混雜的問題
系統開發過程中往往必須考量許多和主要業務流程無關的橫切面考量(Cross-Cutting Concerns)
交易(Transaction)
安全性
例外處理
記錄檔
若沒有仔細切分,容易讓程式碼中商務流程和系統考量交雜在一起,造成程式難以維護
26
將剖面(Aspect)單獨考量
基於重用(Reuse)的原則,可以將這些「橫切面」的處理邏輯抽出來成為一個「Aspect」單獨開發
開發完成後再一次套用在所有具有此需求的商務流程
橫切面考量商務領域考量
27
Pointcuts、Join Points與Advices
Advices
Pointcuts
Join Points
28
寫作Advice類別
public class LogBeforeAdvice {
…
public void before(JoinPoint jointPoint) {
…(要插入的邏輯)
}
}
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>
30
execution( modifiers-pattern?
ret-type-pattern
declaring-type-pattern?
name-pattern(param-pattern)
throws-pattern? )
(Spring 2.0) AOP宣告
<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>
31
(Spring 2.0) AOP Annotations
<bean id="logBeforeAdvice"
class="mypackage.LogBeforeAdvice"/>
<bean id="product" class="mypackage.Product"/>
<aop:aspectj-autoproxy/>
32
(Spring 2.0) 寫作Advice類別
@Aspect
public class LogBeforeAdvice {
…
@Before("execution(* mypackage.Product.*(..))" )
public void before(JoinPoint jointPoint) {
…(要插入的邏輯)
}
}
33
大綱
Spring Framework簡介
Spring 2.0新增功能
Bean容器與Bean設定檔
剖面導向程式設計 (AOP)
永續性與交易支援
Message-Driven POJO
結語
34
(Spring 2.0) 使用tx標籤進行宣告式交易
Transaction
Manager
productDao
<tx:advice>
Transaction Attribute= Require
Isolation Level= Default
execution(* *.ProductDao.*(..))
execution( modifiers-pattern?
ret-type-pattern
declaring-type-pattern?
name-pattern(param-pattern)
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>
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){
…(存取資料)
}
}
// 直接標記在介面的實作成品上
37
Hibernate與JPA
Hibernate Core
開發人員可以選擇只使用JPA以確保 最 大 的 相 容 性 , 或 者 透 過Hibernate API實作更進階的功能,甚至也可以將二者混合使用 !
Hibernate Annotation (JPA)
Hibernate EntityManager
Java Persistence API Hibernate API
Hibernate Annotation (Hibernate)
Hibernate XML 對映檔
38SessionFactoryBean
HibernateTemplate
Spring對Hibernate的封裝
Configuration
hibernate.cfg.xml
SessionFactory Session
Criteria Query
persist()
save()
update()
saveOrUpdate()
delete()
Transaction
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")
private String name;
@Column(name = "price")
private int price;
…(以上三個私有欄位的getter methods及setter methods)…
}
TB_PRODUCT:
名稱 主鍵 型別
id Yes Integer
name No varchar
price No Integer
40
Spring-Hibernate-DAO整合策略
HibernateTemplate
HibernateDaoSupport
SessionFactoryBean
ProductDao
ProductDaoHibernateImpl實作(implements) 繼承(extends)
相依性注入
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();
}
});
}// 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>
43
Spring-Hibernate整合
將SessionFactory注入ProductDaoHibernateImpl
<bean id="productDao“ class="ProductDaoHibernateImpl">
<property name="sessionFactory"
ref="sessionFactory" />
</bean>
ProductDaoHibernateImpl SessionFactoryBean DataSource注入 注入
44
大綱
Spring Framework簡介
Spring 2.0新增功能
Bean容器與Bean設定檔
剖面導向程式設計 (AOP)
永續性支援
Message-Driven POJO
結語
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();
}
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>
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>
48
結語
Spring 2.0 是一個全方位的應用程式框架,主要功能包含了:
輕量級容器
實現依賴注入(Dependency Injection)及非侵入性(No
intrusive)的框架
提供AOP(Aspect-oriented programming)機制
提供對持久層(Persistence)、交易(Transaction)的支援
提供MVC Web框架的實現
對於其它常用企業服務API提供一致的模型封裝
49
Backup
50
小結: Spring Framework的設計理念
透過介面進行系統設計(Programming by interface)
以傳統Java物件為主 (POJO-based Programming)
非侵入性
一致的設定檔格式
51
依賴注入的型式
三種型式
從setter方法注入資源的Setter Injection
從建構子(Constructor)注入的Constructor Injection
透過介面(Interface)注入的Interface injection
Spring Framework支援Setter Injection與Constructor Injection
透過介面的相依性注入具有較強的侵入性,所以Spring
並未採用。
52
黏合用程式碼(Glue Code)
黏合用程式碼」所在的類別會依賴IoC Container
IoC Container
MovieServlet MovieService
53
去除Glue Code
IoC Container
MovieServlet MovieService IoCManagerServlet
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會破壞物件的封裝性
55
AOP觀念與術語(2)
Pointcut
Pointcut用來定義一群Join Points
當呼叫的方法符合Pointcut表示式時,系統會自動將Advice與方法縫合(Weaving)
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>
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);
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);
59
MessageListenerAdapter
上面例子中的MyMessageDrivenPojo 仍然具有相依性
必須繼承javax.jms.MessageListener介面
MessageListenerAdapter
完全切除MDP與JMS的依賴關係
假設使用者自行定義了訊息的處理介面
將介面傳入Adapter做為建構子的參數
public interface MyMessageHandler {
void processMessage(String message);
}
Public class MyMessageHandlerImpl
implements MyMessageHandler { …}
實作不需要實作MessageListener!
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>