課程內容
1. 面向接口(抽象)編程的概念與好處
2. IOC/DI的概念與好處
a) inversion of control
b) dependency injection
3. AOP的概念與好處
4. Spring簡介
5. Spring應用IOC/DI(重要)
a) xml
b) annotation
6. Spring應用AOP(重要)
a) xml
b) annotation
7. Struts2.1.6 +Spring2.5.6 + Hibernate3.3.2整合(重要)
a) opensessionInviewfilter(記住,解決什麼問題,怎麼解決)
8. Spring JDBC
面向接口編程(面向抽象編程)
1. 場景:用戶添加
2. Spring_0100_AbstractOrientedProgramming
a) 不是AOP:Aspect Oriented Programming
3. 好處:靈活
什麼是IOC(DI),有什麼好處
1. 把自己new的東西改爲由容器提供
a) 初始化具體值
b) 裝配
2. 好處:靈活裝配
Spring簡介
1. 項目名稱:Spring_0200_IOC_Introduction
2. 環境搭建
a) 只用IOC
i. spring.jar , jarkata-commons/commons-loggin.jar
3. IOC容器
a) 實例化具體bean
b) 動態裝配
4. AOP支持
a) 安全檢查
b) 管理transaction
Spring IOC配置與應用
1. FAQ:不給提示:
a) window – preferences – myeclipse – xml – xml catalog
b) User Specified Entries – add
i. Location: D:\share\0900_Spring\soft\spring-framework-2.5.6\dist\resources\spring-beans-2.5.xsd
ii. URI: file:///D:/share/0900_Spring/soft/spring-framework-2.5.6/dist/resources/spring-beans-2.5.xsd
iii. KeyType: Schema Location
iv. Key: http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
2. 注入類型
a) Spring_0300_IOC_Injection_Type
b) setter(重要)
c) 構造方法(可以忘記)
d) 接口注入(可以忘記)
3. id vs. name
a) Spring_0400_IOC_Id_Name
b) name可以用特殊字符
4. 簡單屬性的注入
a) Spring_0500_IOC_SimpleProperty
b) <property name=… value=….>
5. <bean 中的scope屬性
a) Spring_0600_IOC_Bean_Scope
b) singleton 單例
c) proptotype 每次創建新的對象
6. 集合注入
a) Spring_0700_IOC_Collections
b) 很少用,不重要!參考程序
7. 自動裝配
a) Spring_0800_IOC_AutoWire
b) byName
c) byType
d) 如果所有的bean都用同一種,可以使用beans的屬性:default-autowire
8. 生命週期
a) Spring_0900_IOC_Life_Cycle
b) lazy-init (不重要)
c) init-method destroy-methd 不要和prototype一起用(瞭解)
9. Annotation第一步:
a) 修改xml文件,參考文檔<context:annotation-config/>
10. @Autowired
a) 默認按類型by type
b) 如果想用byName,使用@Qulifier
c) 寫在private field(第三種注入形式)(不建議,破壞封裝)
d) 如果寫在set上,@qualifier需要寫在參數上
11. @Resource(重要)
a) 加入:j2ee/common-annotations.jar
b) 默認按名稱,名稱找不到,按類型
c) 可以指定特定名稱
d) 推薦使用
e) 不足:如果沒有源碼,就無法運用annotation,只能使用xml
12. @Component @Service @Controller @Repository
a) 初始化的名字默認爲類名首字母小寫
b) 可以指定初始化bean的名字
13. @Scope
14. @PostConstruct = init-method; @PreDestroy = destroy-method;
什麼是AOP
1. 面向切面編程Aspect-Oriented-Programming
a) 是對面向對象的思維方式的有力補充
2. Spring_1400_AOP_Introduction
3. 好處:可以動態的添加和刪除在切面上的邏輯而不影響原來的執行代碼
a) Filter
b) Struts2的interceptor
4. 概念:
a) JoinPoint 釋意:切面與原方法交接點 即 切入點
b) PointCut 釋意:切入點集合
c) Aspect(切面)釋意:可理解爲代理類前說明
d) Advice 釋意:可理解爲代理方法前說明例如@Before
e) Target 釋意:被代理對象 被織入對象
f) Weave 釋意:織入
Spring AOP配置與應用
1. 兩種方式:
a) 使用Annotation
b) 使用xml
2. Annotation
a) 加上對應的xsd文件spring-aop.xsd
b) beans.xml <aop:aspectj-autoproxy/>
c) 此時就可以解析對應的Annotation了
d) 建立我們的攔截類
e) 用@Aspect註解這個類
f) 建立處理方法
g) 用@Before來註解方法
h) 寫明白切入點(execution …….)
i) 讓spring對我們的攔截器類進行管理@Component
3. 常見的Annotation:
a) @Pointcut 切入點聲明以供其他方法使用 , 例子如下:
@Aspect
@Component
public class LogInterceptor {
@Pointcut("execution(public * com.bjsxt.dao..*.*(..))")
public void myMethod(){}
@Around("myMethod()")
public voidbefore(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("method before");
pjp.proceed();
}
@AfterReturning("myMethod()")
public void afterReturning() throws Throwable{
System.out.println("method afterReturning");
}
@After("myMethod()")
public void afterFinily() throws Throwable{
System.out.println("method end");
}
}
b) @Before 發放執行之前織入
c) @AfterReturning 方法正常執行完返回之後織入(無異常)
d) @AfterThrowing 方法拋出異常後織入
e) @After 類似異常的finally
f) @Around 環繞 類似filter , 如需繼續往下執行則需要像filter中執行FilterChain.doFilter(..)對象一樣 執行 ProceedingJoinPoint.proceed()方可,例子如下:
@Around("execution(* com.bjsxt.dao..*.*(..))")
public voidbefore(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("method start");
pjp.proceed();//類似FilterChain.doFilter(..)告訴jvm繼續向下執行
}
4. 織入點語法
a) void !void
b) 參考文檔(* ..)
如果execution(* com.bjsxt.dao..*.*(..))中聲明的方法不是接口實現則無法使用AOP實現動態代理,此時可引入包” cglib-nodep-2.1_3.jar” 後有spring自動將普通類在jvm中編譯爲接口實現類,從而打到可正常使用AOP的目的.
5. xml配置AOP
a) 把interceptor對象初始化
b) <aop:config
i. <aop:aspect …..
1. <aop:pointcut
2. <aop:before
例子:
<beanid="logInterceptor"class="com.bjsxt.aop.LogInterceptor"></bean>
<aop:config>
<!-- 配置一個切面 -->
<aop:aspectid="point" ref="logInterceptor">
<!-- 配置切入點,指定切入點表達式 -->
<!-- 此句也可放到 aop:aspect標籤外依然有效-->
<aop:pointcut
expression=
"execution(public* com.bjsxt.service..*.*(..))"
id="myMethod"/>
<!-- 應用前置通知 -->
<aop:beforemethod="before"pointcut-ref="myMethod"/>
<!-- 應用環繞通知需指定向下進行 -->
<aop:aroundmethod="around"pointcut-ref="myMethod"/>
<!-- 應用後通知 -->
<aop:after-returningmethod="afterReturning"
pointcut-ref="myMethod"/>
<!-- 應用拋出異常後通知 -->
<aop:after-throwingmethod="afterThrowing"
pointcut-ref="myMethod"/>
<!-- 應用最終通知 -->
<aop:aftermethod="afterFinily"
pointcut="execution(public* om.bjsxt.service..*.*(..))"/>
</aop:aspect>
</aop:config>
Spring整合Hibernate
1. Spring 指定datasource
a) 參考文檔,找dbcp.BasicDataSource
i. c3p0
ii. dbcp
iii. proxool
b) 在DAO或者Service中注入dataSource
c) 在Spring中可以使用PropertyPlaceHolderConfigure來讀取Properties文件的內容
2. Spring整合Hibernate
a) <bean .. AnnotationSessionFactoryBean>
i. <property dataSource
ii. <annotatedClasses
b) 引入hibernate 系列jar包
c) User上加Annotation
d) UserDAO或者UserServie 注入SessionFactory
e) jar包問題一個一個解決
3. 聲明式的事務管理
a) 事務加在DAO層還是Service層?Service層(多個dao操作時?)
b) annotation
i. 加入annotation.xsd
ii. 加入txManager bean
iii. <tx:annotation-driven
例如: <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<propertyname="sessionFactory">
<refbean="sessionFactory" />
</property>
</bean>
<tx:annotation-driventransaction-manager="transactionManager"/>
iv. 在需要事務的方法上加:@Transactional
v. 需要注意,Hibernate獲得session時要使用SessionFactory.getCurrentSession不能使用OpenSession
c) @Transactional詳解
i. 什麼時候rollback
1. 運行期異常,非運行期異常不會觸發rollback
2. 必須uncheck (沒有catch)
3. 不管什麼異常,只要你catch了,spring就會放棄管理
4. 事務傳播特性:propagation_required
例如:@Transactional(propagation=Propagation.REQUIRED)等同於(@Transactional)
作用,一個方法聲明瞭@Transactional事務後,其內再調用的方法不需要再聲明@Transactional.
5. read_only
例如:@Transactional(propagation=Propagation.REQUIRED,readOnly=true)
當方法聲明readOnly=true時,該方法及其調用的方法內都不執行insert update等
d) xml(推薦,可以同時配置好多方法)
i. <bean txmanager
ii. <aop:config
1. <aop:pointcut
2. <aop:advisor pointcut-ref advice-ref
iii. <tx:advice: idtransaction-manager =
iv. <propertyname="packagesToScan"> 可定義掃描目標包下所有實體類
例如: <bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource"ref="dataSource" />
<propertyname="hibernateProperties">
<props>
<propkey="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop>
<propkey="hibernate.show_sql">true</prop>
</props>
</property>
<!--
<propertyname="annotatedClasses">
<list>
<value>com.bjsxt.model.TestUser</value>
<value>com.bjsxt.model.Log</value>
</list>
</property>
-->
<!-- 將參數名稱設爲packagesToScan可定義掃描目標包下所有實體類 -->
<propertyname="packagesToScan">
<list>
<value>com.bjsxt.model</value>
</list>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<propertyname="sessionFactory">
<refbean="sessionFactory" />
</property>
</bean>
<aop:config>
<aop:pointcut
expression="execution(public* com.bjsxt.service..*.*(..))"
id="myServiceMethod"/>
<aop:advisor pointcut-ref="myServiceMethod"advice-ref="txAdvice"/>
</aop:config>
<tx:adviceid="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED"/>
<tx:method name="add*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="del*" propagation="REQUIRED"/>
<tx:method name="cancel*" propagation="REQUIRED"/>
<tx:method name="*" read-only="true" />
</tx:attributes>
</tx:advice>
e) HibernateTemplate、HibernateCallback、HibernateDaoSupport(不重要)介紹
i. 設計模式:TemplateMethod(模板方法)
ii. Callback:回調/鉤子函數
iii. 第一種:(建議)
1. 在spring中初始化HibernateTemplate,注入sessionFactory
<bean id="hibernateTemplate"
class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory"ref="sessionFactory" />
</bean>
2. DAO裏注入HibernateTemplate
private HibernateTemplate hibernateTemplate;
@Resource
public void setHibernateTemplate(HibernateTemplatehibernateTemplate) {
this.hibernateTemplate= hibernateTemplate;
}
3. save寫getHibernateTemplate.save();
public void save(TestUser testUser) {
hibernateTemplate.save(testUser);
}
iv. 第二種:
1. 從HibernateDaoSupport繼承(此方法不好用可忽略)
2. 必須寫在xml文件中,無法使用Annotation,因爲set方法在父類中,而且是final的
例如:
首先,新建SuperDAOImpl類(使用Annotation注入--@Component):
@Component
public class SuperDAOImpl {
privateHibernateTemplate hibernateTemplate; //此處定義由spring注入管理
publicHibernateTemplate getHibernateTemplate() {
returnhibernateTemplate;
}
@Resource
public voidsetHibernateTemplate(HibernateTemplate hibernateTemplate) {
this.hibernateTemplate= hibernateTemplate;
}
}
此時,xml中必須要有:
<bean id="hibernateTemplate"
class="org.springframework.orm.hibernate3.HibernateTemplate">
<propertyname="sessionFactory" ref="sessionFactory" />
</bean>
或者,SuperDAOImpl類寫成下面代碼:
@Component
public class SuperDAOImpl extends HibernateDaoSupport {
@Resource(name="sessionFactory")
public voidsetSuperHibernateTemplate(SessionFactory sessionFactory) {
super.setSessionFactory(sessionFactory);
}
}
對應的xml中則可省略
<bean id="hibernateTemplate"………部分
只要包含
<bean id="sessionFactory"……..部分即可
最後,其他類繼承SuperDaoImpl類後便可直接使用HibernateTemplate
@Component("u")
public class UserDAOImpl extends SuperDAOImpl implementsUserDAO {
public voidsave(TestUser testUser) {
this.getHibernateTemplate().save(testUser);
}
}
第3種方法:就是用繼承,所有的DAO extends superDAO ,而superDAO裏面注入了HibernateTemplate .....用的時候注意的是,子類和父類都用同樣的方法,xml或是annotataion
spring整合hibernate的時候使用packagesToScan屬性,可以讓spring自動掃描對應包下面的實體類
Struts2.1.6 +Spring2.5.6 + Hibernate3.3.2
1. 需要的jar包列表
jar包名稱 |
所在位置 |
說明 |
antlr-2.7.6.jar |
hibernate/lib/required |
解析HQL |
aspectjrt |
spring/lib/aspectj |
AOP |
aspectjweaver |
.. |
AOP |
cglib-nodep-2.1_3.jar |
spring/lib/cglib |
代理,二進制增強 |
common-annotations.jar |
spring/lib/j2ee |
@Resource |
commons-collections-3.1.jar |
hibernate/lib/required |
集合框架 |
commons-fileupload-1.2.1.jar |
struts/lib |
struts |
commons-io-1.3.2 |
struts/lib |
struts |
commons-logging-1.1.1 |
單獨下載,刪除1.0.4(struts/lib) |
struts spring |
dom4j-1.6.1.jar |
hibernate/required |
解析xml |
ejb3-persistence |
hibernate-annotation/lib |
@Entity |
freemarker-2.3.13 |
struts/lib |
struts |
hibernate3.jar |
hibernate |
|
hibernate-annotations |
hibernate-annotation/ |
|
hibernate-common-annotations |
hibernate-annotation/lib |
|
javassist-3.9.0.GA.jar |
hiberante/lib/required |
hibernate |
jta-1.1.jar |
.. |
hibernate transaction |
junit4.5 |
|
|
mysql- |
|
|
ognl-2.6.11.jar |
struts/lib |
|
slf4j-api-1.5.8.jar |
hibernate/lib/required |
hibernate-log |
slf4j-nop-1.5.8.jar |
hibernate/lib/required |
|
spring.jar |
spring/dist |
|
struts2-core-2.1.6.jar |
struts/lib |
|
xwork-2.1.2.jar |
struts/lib |
struts2 |
commons-dbcp |
spring/lib/jarkata-commons |
|
commons-pool.jar |
.. |
|
struts2-spring-plugin-2.1.6.jar |
struts/lib |
|
2. BestPractice:
a) 將這些所有的jar包保存到一個位置,使用的時候直接copy
3. 步驟
a) 加入jar包
b) 首先整合Spring + Hibernate
i. 建立對應的package
1. dao / dao.impl / model / service / service.impl/ test
ii. 建立對應的接口與類框架
1. S2SH_01
iii. 建立spring的配置文件(建議自己保留一份經常使用的配置文件,以後用到的時候直接copy改)
iv. 建立數據庫
v. 加入Hibernate註解
1. 在實體類上加相應註解@Entity @Id等
在字段屬性的get方法上加--@Column(name = "表字段名")
2. 在beans配置文件配置對應的實體類,使之受管
vi. 寫dao service的實現
vii. 加入Spring註解
1. 在對應Service及DAO實現中加入@Component,讓spring對其初始化
2. 在Service上加入@Transactional或者使用xml方式(此處建議後者,因爲更簡單)
3. 在DAO中注入sessionFactory
4. 在Service中注入DAO
5. 寫DAO與Service的實現
viii. 寫測試
c) 整合Struts2
i. 結合點:Struts2的Action由Spring產生
ii. 步驟:
1. 修改web.xml加入 struts的filter
如下:
<filter>
<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
2. 再加入spring的listener,這樣的話,webapp一旦啓動,spring容器就初始化了
如下:
<!-- 指定由spring初始化加載xml配置文件 spring與struts結合必備 -->
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
<!-- 默認尋找xml路徑:WEB-INF/applicationContext.xml-->
</listener-class>
</listener>
<!--整個應用的參數服務啓動時讀取.
可指定spring初始化文件路徑位置 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:spring/*applicationContext.xml
</param-value>
</context-param>
3. 規劃struts的action和jsp展現
4. 加入struts.xml
a) 修改配置,由spring替代struts產生Action對象
5. 修改action配置
a) 把類名改爲bean對象的名稱,這個時候就可以使用首字母小寫了
b) @Scope(“prototype”)不要忘記
iii. struts的讀常量:
1. struts-default.xml
2. struts-plugin.xml
3. struts.xml
4. struts.properties
5. web.xml
iv. 中文問題:
1. Struts2.1.8已經修正,只需要改i18n.encoding = gbk
2. 使用spring的characterencoding
例:
<!-- 過濾器相關配置 ========字符編碼過濾======== -->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>
org.springframework.web.filter.CharacterEncodingFilter
</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
3. 需要嚴格注意filter的順序
4. 需要加到Struts2的filter前面
v. LazyInitializationException
1. OpenSessionInViewFilter
2. 需要嚴格順序問題
3. 需要加到struts2的filter前面
附:
1.
@Autowired 與@Resource都可以用來裝配bean. 都可以寫在屬性定義上,或寫在set方法上
@Autowired (srping提供的)默認按類型裝配
@Resource ( j2ee提供的 )默認按名稱裝配,當找不到(不寫name屬性)名稱匹配的bean再按類型裝配.
可以通過@Resource(name="beanName")指定被注入的bean的名稱,要是指定了name屬性,就用字段名去做name屬性值,一般不用寫name屬性.
@Resource(name="beanName")指定了name屬性,按名稱注入但沒找到bean,就不會再按類型裝配了.
@Autowired 與@Resource可作用在屬性定義上, 就不用寫set方法了(此方法不提倡);
2.
a.
Action類前加@Component,則Action可由spring來管理,例子如下:
Action中寫:
@Component("u") //spring管理註解
@Scope("prototype") //多態
public class UserAction extends ActionSupportimplements ModelDriven{
//內部屬性需要有get/set方法且需要set方法前加@Resource或@Autowired
}
Struts2配置文件中寫
<action name="u"class="u">
Jsp中
<form method="post"action="u.do" >
b.
Action中也可不加@Component,Action由struts2-spring-plugin管理。此時,如果Action中定義的屬性有set方法則@Autowired與@Resource也可不寫,但是如果沒有set方法,則需要在屬性前加上@Autowired或@Resource才能生效。
3.
Hibernate如果使用load來查詢數據,例如:
Service中:
public User loadById(int id) {
returnthis.userDao.loadById(id);
}
DAO中:
public User loadById(int id) {
return(User)this.hibernateTemplate.load(User.class, id);
}
此時,session(應該說的是Hibernate的session)在事物結束(通常是service調用完)後自動關閉。由於使用的是load獲取數據,在jsp頁面申請取得數據時才真正的執行sql,而此時session已經關閉,故報錯。
Session關閉解決方法:
在web.xml中增加filter—openSessionInView,用於延長session在jsp調用完後再關閉
如下所示:
注意:filter–openSessionInView一定要在 filter—struts2之前調用
Filter順序—先進後出!
<filter>
<filter-name>OpenSessionInViewFilter</filter-name>
<filter-class>
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
</filter-class>
<init-param>
<param-name>sessionFactoryBeanName</param-name>
<param-value>sf</param-value>(此處默認指定的sessionFactory應爲” sessionFactory”默認可省略此行如果shring配置文件中配置的sessionFactory爲”sf”則此處需要寫sf 一般用不到)
</init-param>
</filter>
<filter-mapping>
<filter-name>OpenSessionInViewFilter </filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
跨數據的事務管理用jta不用hibernate,用了hibernate的事務管理之後,就不需要使用try catchfinally來對異常捕獲回滾
Action及其set屬性有struts.xml自動裝配,如果struts.xml裏的action的class屬性設爲spring裏bean的id屬性值,則struts.xml不會自動裝配action及其set屬性,而是由spring來裝配,還有struts.xml來裝配action是通過屬性的名字來裝配的。
Spring自動化測試 opensessioninviewIntercepter