1、Spring開源框架的簡介 html
2、Spring下IOC容器和DI(依賴注入Dependency injection)java
3、Spring下面向切面編程(AOP)和事務管理配置 程序員
1、Spring開源框架的簡介 web
Spring是一個開源框架,Spring是於2003 年興起的一個輕量級的Java 開發框架,由Rod Johnson 在其著做Expert One-On-One J2EE Development and Design中闡述的部分理念和原型衍生而來。它是爲了解決企業應用開發的複雜性而建立的。Spring使用基本的JavaBean來完成之前只可能由EJB完成的事情。然而,Spring的用途不只限於服務器端的開發。從簡單性、可測試性和鬆耦合的角度而言,任何Java應用均可以從Spring中受益。 簡單來講,Spring是一個輕量級的控制反轉(IoC)和麪向切面(AOP)的容器框架。正則表達式
spring的基本框架主要包含六大模塊:DAO、ORM、AOP、JEE、WEB、COREspring
Spring DAO:Spring提供了對JDBC的操做支持:JdbcTemplate模板工具類 。sql
Spring ORM:Spring能夠與ORM框架整合。例如Spring整合Hibernate框架,其中Spring還提供HibernateDaoSupport工具類,簡化了Hibernate的操做 。數據庫
Spring WEB:Spring提供了對Struts、Springmvc的支持,支持WEB開發。與此同時Spring自身也提供了基於MVC的解決方案 。express
Spring AOP:Spring提供面向切面的編程,能夠給某一層提供事務管理,例如在Service層添加事物控制 。編程
Spring JEE:J2EE開發規範的支持,例如EJB 。
Spring Core:提供IOC容器對象的建立和處理依賴對象關係 。
2、Spring下IOC容器和DI(依賴注入Dependency injection)
IOC容器:就是具備依賴注入功能的容器,是能夠建立對象的容器,IOC容器負責實例化、定位、配置應用程序中的對象及創建這些對象間的依賴。一般new一個實例,控制權由程序員控制,而"控制反轉"是指new實例工做不禁程序員來作而是交給Spring容器來作。。在Spring中BeanFactory是IOC容器的實際表明者。
DI(依賴注入Dependency injection) :在容器建立對象後,處理對象的依賴關係。
依賴注入spring的注入方式:
-
-
- set注入方式
- 靜態工廠注入方式
- 構造方法注入方式
- 基於註解的方式
-
一、set注入方式:
控制層代碼:
private OrderServiceImp orderService; public void setOrderService(OrderServiceImp orderService) { this.orderService = orderService; }
Spring配置XML文件:其中配置聲明OrderAction類存在屬性orderService。程式運行時候,會將已經實例化的orderService對象調用setOrderService方式注入。
<bean name="orderAction" class="com.pec.action.OrderAction"> <property name="orderService" ref="orderService"></property> </bean> <bean name="orderService" class="com.pec.service.imp.OrderServiceImp"></bean>
二、構造器注入方式:
控制層代碼:
private OrderServiceImp orderService; public OrderAction(OrderServiceImp orderService) { this.orderService = orderService; }
Spring配置XML文件:
<bean name="orderAction" class="com.pec.action.OrderAction"> <constructor-arg ref="orderService"></constructor-arg> </bean> <bean name="orderService" class="com.pec.service.imp.OrderServiceImp"></bean>
三、基於註解的方式(推薦使用,比較便捷少配置)
控制層代碼:
@Autowired //@Resource private OrderServiceImp orderService;
服務層代碼:
@Service("orderService") public class OrderServiceImp implements IOrderService { @Autowired private JavaOrderMDaoImp javaOrderMDao; @Autowired private JavaOrderDDaoImp javaOrderDDao; @Override public List<JavaOrderMList> findOrderM(OrderSearch search) { return javaOrderMDao.findJavaOrderM(search); } @Override public List<JavaOrderDList> findOrderD(OrderSearch search) { return javaOrderDDao.findJavaOrderD(search); } }
DAO層代碼:
@Repository("javaOrderMDao") public class JavaOrderMDaoImp extends BaseHibernateDAO<JavaOrderM, Serializable> implements IJavaOrderMDao {...}
@Repository("javaOrderDDao") public class JavaOrderDDaoImp extendsBaseHibernateDAO<JavaOrderD, Serializable> implements IJavaOrderDDao {...}
注意點:
⑴ 持久層DAO層註解Repository中規定了名稱,在Service層中聲明名稱必須一致。
⑵ 服務層Service層註解Service中規定了名稱,在控制層中聲明的名稱必須一致。
⑶ 註解方式注入依賴註解:
@Component 把對象加入ioc容器,對象引用名稱是類名,第一個字母小寫 @Component(「name」) 把指定名稱的對象,加入ioc容器 @Repository 主要用於標識加入容器的對象是一個持久層的組件(類) @Service 主要用於標識加入容器的對象是一個業務邏輯層的組件 @Controller 主要用於標識加入容器的對象是一個控制層的組件 @Resource 注入屬性(DI), 會從容器中找對象注入到@Resource修飾的對象上 @Autowired 注入屬性(DI), 會從容器中找對象注入到@Autowired修飾的對象上
⑷ 註解能夠簡化配置,提高開發效率,可是也不利於後期維護。
3、Spring下面向切面編程(AOP)和事務管理配置
AOP就是縱向的編程,如業務1和業務2都須要一個共同的操做,與其往每一個業務中都添加一樣的代碼,不如寫一遍代碼,讓兩個業務共同使用這段代碼。在平常有訂單管理、商品管理、資金管理、庫存管理等業務,都會須要到相似日誌記錄、事務控制、權限控制、性能統計、異常處理及事務處理等。AOP把全部共有代碼所有抽取出來,放置到某個地方集中管理,而後在具體運行時,再由容器動態織入這些共有代碼。
AOP涉及名稱:
切面(Aspect):其實就是共有功能的實現。如日誌切面、權限切面、事務切面等。在實際應用中一般是一個存放共有功能實現的普通Java類,之因此能被AOP容器識別成切面,是在配置中指定的。
通知(Advice):是切面的具體實現。以目標方法爲參照點,根據放置的地方不一樣,可分爲前置通知(Before)、後置通知(AfterReturning)、異常通知(AfterThrowing)、最終通知(After)與環繞通知(Around)5種。在實際應用中一般是切面類中的一個方法,具體屬於哪類通知,一樣是在配置中指定的。
鏈接點(Joinpoint):就是程序在運行過程當中可以插入切面的地點。例如,方法調用、異常拋出或字段修改等,但Spring只支持方法級的鏈接點。
切入點(Pointcut):用於定義通知應該切入到哪些鏈接點上。不一樣的通知一般須要切入到不一樣的鏈接點上,這種精準的匹配是由切入點的正則表達式來定義的。
目標對象(Target):就是那些即將切入切面的對象,也就是那些被通知的對象。這些對象中已經只剩下乾乾淨淨的核心業務邏輯代碼了,全部的共有功能代碼等待AOP容器的切入。
代理對象(Proxy):將通知應用到目標對象以後被動態建立的對象。能夠簡單地理解爲,代理對象的功能等於目標對象的核心業務邏輯功能加上共有功能。代理對象對於使用者而言是透明的,是程序運行過程當中的產物。
織入(Weaving):將切面應用到目標對象從而建立一個新的代理對象的過程。這個過程能夠發生在編譯期、類裝載期及運行期,固然不一樣的發生點有着不一樣的前提條件。譬如發生在編譯期的話,就要求有一個支持這種AOP實現的特殊編譯器;發生在類裝載期,就要求有一個支持AOP實現的特殊類裝載器;只有發生在運行期,則可直接經過Java語言的反射機制與動態代理機制來動態實現。
Spring使用AOP配置事務管理由三個部分組成,分別是DataSource、TransactionManager和代理機制這三部分,不管哪一種配置方式,通常變化的只是代理機制這部分。DataSource、TransactionManager這兩部分只是會根據數據訪問方式有所變化,好比使用hibernate進行數據訪問時,DataSource實際爲SessionFactory,TransactionManager的實現爲HibernateTransactionManager。
spring事務配置的五種方式:每一個Bean都有一個代理、全部Bean共享一個代理基類、使用攔截器、使用tx標籤配置的攔截器、全註解
一、使用tx標籤配置的攔截器
<!--四、配置hibernate屬性 --> <!--引入db.properties屬性文件 --> <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location" value="classpath:db.properties"></property> </bean> <!-- 配置數據源,鏈接池使用c3p0,詳細信息參見hibernate官方文檔"基礎配置章節" --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close" dependency-check="none"> <property name="driverClass"> <value>${datasource.driverClassName}</value> </property> <property name="jdbcUrl"> <value>${datasource.url}</value> </property> <property name="user"> <value>${datasource.username}</value> </property> <property name="password"> <value>${datasource.password}</value> </property> <property name="acquireIncrement"> <!--當鏈接池中的鏈接耗盡的時候c3p0一次同時獲取的鏈接數。Default: 3 --> <value>${c3p0.acquireIncrement}</value> </property> <property name="initialPoolSize"> <!--初始化時獲取的鏈接數,取值應在minPoolSize與maxPoolSize之間。Default: 3 --> <value>${c3p0.initialPoolSize}</value> </property> <property name="minPoolSize"> <!--鏈接池中保留的最小鏈接數。 --> <value>${c3p0.minPoolSize}</value> </property> <property name="maxPoolSize"> <!--鏈接池中保留的最大鏈接數。Default: 15 --> <value>${c3p0.maxPoolSize}</value> </property> <property name="maxIdleTime"> <!--最大空閒時間,60秒內未使用則鏈接被丟棄。若爲0則永不丟棄。Default: 0 --> <value>${c3p0.maxIdleTime}</value> </property> <property name="idleConnectionTestPeriod"> <!--每60秒檢查全部鏈接池中的空閒鏈接。Default: 0 --> <value>${c3p0.idleConnectionTestPeriod}</value> </property> <property name="maxStatements"> <!-- JDBC的標準參數,用以控制數據源內加載的PreparedStatements數量。但因爲預緩存的statements 屬於單個connection而不是整個鏈接池。因此設置這個參數須要考慮到多方面的因素。 若是maxStatements與maxStatementsPerConnection均爲0,則緩存被關閉。Default: 0 --> <value>${c3p0.maxStatements}</value> </property> <property name="numHelperThreads"> <!-- C3P0是異步操做的,緩慢的JDBC操做經過幫助進程完成。擴展這些操做能夠有效的提高性能, 經過多線程實現多個操做同時被執行。Default: 3 --> <value>${c3p0.numHelperThreads}</value> </property> </bean> <!--配置 sessionFactory --> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource" ref="dataSource"> </property> <!-- hibernate的設置 --> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">${hibernate.dialect}</prop> <prop key="hibernate.show_sql"> ${hibernate.show_sql} </prop> <prop key="hibernate.jdbc.fetch_size">${hibernate.jdbc.fetch_size}</prop> <prop key="hibernate.jdbc.batch_size">${hibernate.jdbc.batch_size}</prop> <prop key="hibernate.connection.release_mode">${hibernate.connection.release_mode}</prop> <prop key="hibernate.format_sql">${hibernate.format_sql}</prop> <prop key="hibernate.connection.SetBigStringTryClob">true</prop> </props> </property> <!-- anotation註解掃描實體類 --> <property name="packagesToScan"> <list> <value>com.pec.model</value> </list> </property> </bean> <!--五、Spring 配置聲明式事物 --> <!-- 配置事務 --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"></property> </bean> <!-- 配置事務範圍 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="get*" read-only="false" propagation="NOT_SUPPORTED" /> <tx:method name="find*" read-only="false" propagation="NOT_SUPPORTED" /> <tx:method name="save*" propagation="REQUIRED" /> <tx:method name="update*" propagation="REQUIRED" /> <tx:method name="delete*" propagation="REQUIRED" /> <tx:method name="create*" propagation="REQUIRED" /> <tx:method name="anscy*" propagation="REQUIRED" /> </tx:attributes> </tx:advice> <!-- 定義切面 --> <aop:config proxy-target-class="true"> <aop:pointcut id="pointcut" expression="execution(* com.pec.service..*.*(..))" /> <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut" /> </aop:config>
有幾點須要說明:
⑴ pointcut中的三個"*"中,第一個*表明返回值,第二*表明service下子包,第三個*表明方法名,「(..)」表明方法參數。
⑵ 此時配置的切點在Service層,方法命名須要按照以上advice通知點開頭命名。
⑶ 按照規定命名方法,會受到Spring事務的管控,保持操做的一致性。例如向數據庫插入100條數據,前面99條記錄都正常執行直至第100條出現錯誤,則事務管控會回滾到執行前的初始狀態。
二、使用Bean代理
<?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:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd" default-autowire="default"> <!-- <bean name="userManager" class="com.tgb.manager.UserManagerImpl"></bean> <bean name="userController" class="com.tgb.web.UserController"> <property name="userManager" ref="userManager"></property> </bean> --> <context:component-scan base-package="com.tgb.dao" /> <context:component-scan base-package="com.tgb.entity" /> <context:component-scan base-package="com.tgb.manager" /> <context:component-scan base-package="com.tgb.web" /> <!-- 引入init.properties中屬性 --> <bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:config/spring/jdbc.properties</value> </list> </property> </bean> <!-- 配置數據源,鏈接池使用c3p0,詳細信息參見hibernate官方文檔"基礎配置章節" --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" > <property name="driverClass" value="${datasource.driverClassName}"></property> <property name="jdbcUrl" value="${datasource.url}"></property> <property name="user" value="${datasource.username}"></property> <property name="password" value="${datasource.password}"></property> </bean> <!-- 配置SessionFactory --> <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect"> ${hibernate.dialect} </prop> <prop key="hibernate.show_sql"> ${hibernate.show_sql} </prop> <prop key="hibernate.jdbc.fetch_size"> ${hibernate.jdbc.fetch_size} </prop> <prop key="hibernate.jdbc.batch_size"> ${hibernate.jdbc.batch_size} </prop> <prop key="hibernate.connection.release_mode"> ${hibernate.connection.release_mode} </prop> <prop key="hibernate.format_sql"> ${hibernate.format_sql} </prop> <prop key="hibernate.connection.SetBigStringTryClob">true</prop> </props> </property> <!-- anotation註解掃描實體類 --> <property name="annotatedClasses"> <list> <value>com.tgb.entity.User</value> </list> </property> </bean> <!-- 配置一個事務管理器 將事務與Hibernate關聯--> <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"/> </bean> <!-- 配置事務範圍,使用代理的方式 --> <bean id="transactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true"> <!-- 爲事務代理bean注入事務管理器--> <property name="transactionManager" > <ref bean="transactionManager"/> </property> <!--設置事務屬性範圍--> <property name="transactionAttributes"> <props> <prop key="add*">PROPAGATION_REQUIRED,-Exception</prop> <prop key="get">PROPAGATION_REQUIRED,-Exception</prop> <prop key="update*">PROPAGATION_REQUIRED,-myException</prop> <prop key="del*">PROPAGATION_REQUIRED</prop> <prop key="*">PROPAGATION_REQUIRED</prop> </props> </property> </bean> <bean id="userDao" class="com.tgb.dao.UserDaoImpl"> <property name="sessionFactory" ref="sessionFactory"></property> </bean> <bean id="userManagerBase" class="com.tgb.manager.UserManagerImpl"> <property name="userDao" ref="userDao"></property> </bean> <!-- 此處爲代理 --> <bean name="userManager" parent="transactionProxy"> <property name="target" ref="userManagerBase"></property> </bean> </beans>
參考連接:
http://www.cnblogs.com/andy6163/p/Andy.html 簡單理解——面向切面編程(AOP)
http://blog.csdn.net/moreevan/article/details/11977115 pring AOP 實現原理
http://blog.csdn.net/it_man/article/details/5074371 spring事務配置的五種方式
http://www.cnblogs.com/rushoooooo/archive/2011/08/28/2155960.html Spring聲明式事務配置管理方法