spring的另一個重要特性是AOP(
Aspect Oriented Programming)面向切面的編程,spring的AOP特性使得對于使用了該特性的項目的可維護性,易拓展性和開發難易度等等都有了不同程度的改善。AOP特性能夠使得項目中的某些操作,在執行到某一個指定環節的時候,可以額外的去執行開發者指定的操作,這些操作往往都是具有共通性,而且可能和操作本身所包含的業務邏輯沒有直接的關系,比如對數據庫的訪問,涉及變更數據庫內容的操作需要精準的記錄日志;每當產生異常或者錯誤信息的時候,也需要記錄錯誤信息;對服務器敏感資源進行訪問的時候需要對用戶的權限進行校驗等。在哪些環節添加處理,做怎樣的處理,都可以由開發者自定義,十分靈活,而且在開發業務邏輯和流程的時候大可不必去考慮這些共同性質的處理,讓主要精力都投入在業務的實現上,這樣一來,開發效率會大大提高。
先從一個靜態代理的例子來感受一下這種切入式的編程
IUserDao
1 package org.duyt.dao;
2 public interface IUserDao {
3 public void add();
4 }
UserDao
1 package org.duyt.dao.impl;
2
3 import org.duyt.dao.IUserDao;
4 import org.springframework.context.annotation.Scope;
5 import org.springframework.stereotype.Repository;
6
7 @Repository("userDao")
8 @Scope("singleton")
9 public class UserDao implements IUserDao {
10 public void add() {
11 System.out.println("用戶增加方法");
12 }
13 }
14
一個很單純的接口實現。倘若這就是一個成品了,測試通過沒有問題,可以上線使用。一段時間之后,需要加入日志的功能,那么問題來了,挖掘機哪...噢不對,該如何添加呢?
或許會馬上想到,直接該啊。那么問題又來了,挖...噢不,直接修改的話,代碼就需要測試,而且萬一需要修改的地方很多呢,豈不是很痛苦,況且直接修改源代碼還違背了OCP原則,絕對不推薦。這時候就可以考慮使用代理類來給源代碼增加新功能。
代理,望文生義,白話就是“你要做的事兒我不僅能給你做了,而且除此之外我還能多做別的”,定義一個UserProxyDao
1 package org.duyt.dao.impl;
2
3 import javax.annotation.Resource;
4
5 import org.duyt.dao.IUserDao;
6 import org.duyt.util.Logger;
7 import org.springframework.context.annotation.Scope;
8 import org.springframework.stereotype.Repository;
9
10 @Repository("userProxyDao")
11 @Scope("singleton")
12 public class UserProxyDao implements IUserDao {
13
14 @Resource
15 private IUserDao userDao;
16
17 public void add() {
18 Logger.info("使用代理,為用戶增加方法添加日志");
19 userDao.add();
20
21 }
22
23 }
24
在代理中,將需要拓展功能的對象作為代理的屬性注入,然后在需要拓展的方法前后追加需要的功能。在此之后,在給service的IuserDao對象注入實例的時候,要使用代理的對象@Resource(name = "userProxyDao"),測試一下
1 package org.duyt.test;
2
3 import org.duyt.action.UserAction;
4 import org.junit.Test;
5 import org.springframework.beans.factory.BeanFactory;
6 import org.springframework.context.support.ClassPathXmlApplicationContext;
7
8 public class IocTest {
9
10 private BeanFactory factory = new ClassPathXmlApplicationContext("beans.xml");
11
12 @Test
13 public void test(){
14 //測試代理依賴注入
15 UserAction ua = (UserAction) factory.getBean("userAction");
16 ua.addUser();
17 }
18
19 }
20
結果:
使用代理,為用戶增加方法添加日志
用戶增加方法
由于IOC和AOP的特性,你會發現你要做的更改十分的少,僅僅只是新增了一個代理類,并修改了注入的對象。雖然靜態的代理可以實現我們的需求,但是畢竟不靈活,一旦修改涉及的方法和類一多,那簡直就是純體力活了,一個類的拓展就需要對應一個代理類,一個代理類中還需要涵蓋所有需要拓展的方法,并且保證原有功能不受影響,如此一來,功能拓展這一舉動就需要投入極大的成本,入不敷出。