Spring AOP主要就是經過動態代理來實現,而Ioc是經過反射來實現,將建立對象和對象之間的依賴管理交給IoC容器來作,完成對象之間的解耦。java
舉個反射的例子,以下:redis
public class Car { private String brand; private String color; private int maxSpeed; public Car() { System.out.println("init car!!"); } public Car(String brand, String color, int maxSpeed) { this.brand = brand; this.color = color; this.maxSpeed = maxSpeed; } public void introduce() { System.out.println("brand:" + brand + ";color:" + color + ";maxSpeed:" + maxSpeed); } public String getBrand() { return brand; } public void setBrand(String brand) { this.brand = brand; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public int getMaxSpeed() { return maxSpeed; } public void setMaxSpeed(int maxSpeed) { this.maxSpeed = maxSpeed; } }
public class ReflectTest { public static Car initByDefaultConst() throws Throwable { // loadClass()方法必須使用全額限定名 ClassLoader loader = Thread.currentThread().getContextClassLoader(); // 每個類在JVM中都擁有一個對應的java.lang.Class對象,用來描述類結構信息 // Class clazz = loader.loadClass("reflect.Car"); Class clazz = Class.forName("reflect.Car"); Constructor cons = clazz.getDeclaredConstructor((Class[]) null); Car car = (Car) cons.newInstance(); Method setBrand = clazz.getMethod("setBrand", String.class); setBrand.invoke(car, "紅旗CA72"); Method setColor = clazz.getMethod("setColor", String.class); setColor.invoke(car, "黑色"); Method setMaxSpeed = clazz.getMethod("setMaxSpeed", int.class); setMaxSpeed.invoke(car, 200); return car; } public static Car initByParamConst() throws Throwable { ClassLoader loader = Thread.currentThread().getContextClassLoader(); Class clazz = loader.loadClass("reflect.Car"); Constructor cons = clazz.getDeclaredConstructor(new Class[] { String.class, String.class, int.class }); Car car = (Car) cons.newInstance(new Object[] { "吉利TOPMIX", "綠色", 120 }); return car; } public static void main(String[] args) throws Throwable { Car car1 = initByDefaultConst(); Car car2 = initByParamConst(); car1.introduce(); car2.introduce(); } }
init car!! brand:紅旗CA72;color:黑色;maxSpeed:200 brand:吉利TOPMIX;color:綠色;maxSpeed:120
每個類在JVM中都擁有一個對應的java.lang.Class對象,它提供了類結構信息的描述。數組、枚舉、註解甚至void都有對應的Class對象。能夠從Class對象中獲取構造函數、成員變量、方法等類元素的反射對象,並以編程的方式經過這些反射對目標類對象進行操做。spring
Spring中的事務徹底基於數據庫的事務,若是數據庫引擎使用MyISAM引擎,那Spring的事務實際上是不起做用的。另外,Spring爲開發者提供的與事務相關的特性就是事務的傳播行爲,以下:數據庫
事務傳播行爲類型apache |
說明編程 |
propagation_required數組 |
若是當前沒有事務,就新建一個事務,若是已經存在一個事務中,加入到這個事務中。這是最多見的選擇(Spring默認的事務傳播行爲)app |
propagation_supports數據庫設計 |
支持當前事務,若是當前沒有事務,就以非事務方式執行函數 |
propagation_mandatory(託管) |
使用當前的事務,若是當前沒有事務,就拋出異常 |
propagation_requireds_new |
新建事務,若是當前存在事務,把當前事務掛起 |
propagation_not_supported |
以非事務方式執行操做,若是當前存在事務,就把當前事務掛起 |
propagation_never |
以非事務方式執行,若是當前存在事務,則拋出異常 |
propagation_nested |
若是當前存在事務,則在嵌套事務內執行。若是當前沒有事務,則執行與propagation_required相似的操做,也就是新建一個事務。父事務回滾,嵌套的事務也要回滾。
|
Spring經過事務傳播行爲控制當前的事務如何傳播到被嵌套調用的目標服務接口方法中。
Spring能夠配置事務的屬性,可是隔離級別、讀寫事務屬性、超時時間與回滾設置等都交給了JDBC,真正本身實現的只有事務的傳播行爲。那麼何時發生事務的傳播行爲呢?
public class ForumService { private UserService userService; @Transactional(propagation = Propagation.REQUIRED) public void addTopic() { // add Topic this.updateTopic(); userService.addCredits(); } @Transactional(propagation = Propagation.REQUIRED) public void updateTopic() { // add Topic } public void setUserService(UserService userService) { this.userService = userService; } }
看一下userService中的addCredits()方法,以下:
public class UserService { @Transactional(propagation = Propagation.REQUIRES_NEW) public void addCredits() { } }
而後測試下:
forumService.addTopic();
開啓了Spring4日誌的DEBUG模式後,輸出以下:
- Returning cached instance of singleton bean 'txManager' - Creating new transaction with name [com.baobaotao.service.ForumService.addTopic]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; '' - Acquired Connection [org.apache.commons.dbcp.PoolableConnection@1948ea69] for JDBC transaction - Switching JDBC Connection [org.apache.commons.dbcp.PoolableConnection@1948ea69] to manual commit - Suspending current transaction, creating new transaction with name [com.baobaotao.service.UserService.addCredits] - Acquired Connection [org.apache.commons.dbcp.PoolableConnection@773e2eb5] for JDBC transaction - Switching JDBC Connection [org.apache.commons.dbcp.PoolableConnection@773e2eb5] to manual commit - Initiating transaction commit - Committing JDBC transaction on Connection [org.apache.commons.dbcp.PoolableConnection@773e2eb5] - Releasing JDBC Connection [org.apache.commons.dbcp.PoolableConnection@773e2eb5] after transaction - Returning JDBC Connection to DataSource - Resuming suspended transaction after completion of inner transaction - Initiating transaction commit - Committing JDBC transaction on Connection [org.apache.commons.dbcp.PoolableConnection@1948ea69] - Releasing JDBC Connection [org.apache.commons.dbcp.PoolableConnection@1948ea69] after transaction - Returning JDBC Connection to DataSource
清楚的看到調用addCredis()方法時建立了一個新的事務,而在這個方法中調用addCredits()方法時,因爲這個方法的事務傳播行爲爲progation_required_new,因此掛起了當前的線程,又建立了一個新的線程。可是對於this.updateTopic()方法調用時,因爲這個
方法的事務仍然爲propagation_required,因此在當前線程事務中執行便可。
在使用事務中咱們須要作到儘可能避免死鎖、儘可能減小阻塞,根據不一樣的數據庫設計和性能要求進行所須要的隔離級別,纔是最恰當的。具體如下方面須要特別注意:
A、 事務操做過程要儘可能小,能拆分的事務要拆分開來
B、 事務操做過程不該該有交互(系統交互,接口調用),由於交互等待的時候,事務並未結束,可能鎖定了不少資源
C、 事務操做過程要按同一順序訪問對象。(避免死鎖的狀況產生)
D、 提升事務中每一個語句的效率,利用索引和其餘方法提升每一個語句的效率能夠有效地減小整個事務的執行時間。
E、 查詢時能夠用較低的隔離級別,特別是報表查詢的時候,能夠選擇最低的隔離級別(未提交讀)。
參考:http://blog.csdn.net/arvinrong/article/details/7756167
SpringMVC設計思路:將整個處理流程規範化,並把每個處理步驟分派到不一樣的組件中進行處理。
這個方案實際上涉及到兩個方面:
l 處理流程規範化 —— 將處理流程劃分爲若干個步驟(任務),並使用一條明確的邏輯主線將全部的步驟串聯起來
l 處理流程組件化 —— 將處理流程中的每個步驟(任務)都定義爲接口,併爲每一個接口賦予不一樣的實現模式
處理流程規範化是目的,對於處理過程的步驟劃分和流程定義則是手段。於是處理流程規範化的首要內容就是考慮一個通用的Servlet響應程序大體應該包含的邏輯步驟:
l 步驟1—— 對Http請求進行初步處理,查找與之對應的Controller處理類(方法) ——HandlerMapping
l 步驟2—— 調用相應的Controller處理類(方法)完成業務邏輯 ——HandlerAdapter
l 步驟3—— 對Controller處理類(方法)調用時可能發生的異常進行處理 ——HandlerExceptionResolver
l 步驟4—— 根據Controller處理類(方法)的調用結果,進行Http響應處理 ——ViewResolver
正是這基於組件、接口的設計,支持了SpringMVC的另外一個特性:行爲的可擴展性。