spring開發aop應用有三種方法: 一:Spring 1.2版本中通過ProxyFactoryBean來實現aop,即通過動態代理來實現的,Aspect必須繼承MethodBeforeAdvice,MethodAfterAdvice等 <!--被代理的對象--> <bean id="man" class="Man"> <property name="name"> <value type="java.lang.String">張三</value> </property> </bean> <!--繼承了MethodBeforeAdvice類的 Aspect-> <bean id="fbi" class="FBI" /> <bean id="civilian" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target"> <ref bean="man" /> </property> <property name="interceptorNames"> <list> <value>fbi</value> </list> </property> </bean> 二:Spring 2.0 AOP 應用 需要改的是FBI 這個類,而且它也不需要再實現某些接口了 public class FBI { public void before(JoinPoint point){ Man man = (Man)point.getTarget(); System.err.println("FBI 發現" + man.getName() + "正在進行 " + point.getSignature().getName() + " 活動。"); } } 注意這個類裏面的方法 before(JoinPoint),方法名可以是任意的,可以帶一個JoinPoint 類 型的參數,也可以不帶參數直接寫成before(),但是這個連接點(JoinPoint)對象帶來了所 有和這次方法調用有關的信息,包括方法參數,目標對象等等,所以一般要做日誌記錄的話 會帶上它。 接下來是測試類的代碼,和以前的幾乎沒有任何不同,只不過現在直接訪問的是man 這個bean。 <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"> <bean id="fbi" class="FBI" /> <bean id="man" class="Man"> <property name="name"> <value type="java.lang.String">張三</value> </property> </bean> <aop:config> <aop:pointcut id="manPointcut" expression="execution(* Man.*(..))" /> <aop:aspect id="beforeExample" ref="fbi"> <aop:before pointcut-ref="manPointcut" method="before" /> </aop:aspect> </aop:config> </beans> 1. 配置文件的開頭加入了aop 命名空間,如代碼中粗斜體所示。 2. 使用aop:config 標籤來定義AOP,不是使用ProxyFactoryBean 來定義一個新的 bean。 一個是人的對象,另 一個則是聯邦調查局的探員。而aop:config 中定義了所有的AOP 設置信息。aop:pointcut 定義了一個切入點,id 給出了這個切入點的唯一名字,而expression 定義了切入點的表達 式,那麼這個定義到底表示了什麼信息呢?它的意思是表示一種場景,即執行(execution) Man 對象的所有方法的這種情況,這就是表達式execution(* Man.*(..))的意義所在, Man.*(..)表示Man 類的所有方法。接下來呢,需要定義一個切面,用aop:aspect 來定義, 它的ref 屬性指定了這個切面所對應的bean 定義的id,這裏指向fbi 這個bean 類;子標籤 aop:before 則指示了當發生了名爲manPointcut 的切入點(情況)前(用pointcut-ref 屬性 指定,pointcut-ref=”manPointcut”),就調用名爲before 的方法,這個方法位於aspect 裏 面的引用的那個bean 中,這裏是fbi(即ref=”fbi”)。其實Spring 執行到這裏後,會自動的 把這些代碼翻譯成底層的Bean 定義(後臺依然會採用ProxyFactoryBean 這樣的機制), 然後把對應的獲取bean 的操作直接委託給代理類,這就是爲什麼上文提到的測試類只需要 訪問原來的man 這個bean,對應的攔截類就會被執行的原因。從這裏看到Spring 2.0 中要 定義一個AOP 的bean 類,仍然是比較複雜的,XML 文件和概念都增加了很多,需要讀者 慢慢來學習和理解。 三使用標註(@AspectJ)實現AOP 的一個庫來做切點(pointcut)解析和匹配。 爲了在Spring 配置中使用@AspectJ aspects,你必須首先啓用Spring 對基於@AspectJ aspects 的配置支持,自動代理(autoproxying)基於通知是否來自這些切面。 自動代理是 指Spring 會判斷一個bean 是否使用了一個或多個切面通知,並據此自動生成相應的代理 以攔截其方法調用,並且確認通知是否如期進行。 通過在你的Spring 的配置文件中引入下列元素來啓用Spring 對@AspectJ 的支持: <aop:aspectj-autoproxy/> 也可以通過在你的application context 中添加如下定義來啓用@AspectJ 支持: <bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyC reator" /> 你需要在你的應用程序的classpath 中引入兩個AspectJ 庫:aspectjweaver.jar 和 aspectjrt.jar。我們這裏用的MyEclipse,在添加Spring 開發功能時已經自動的加入了這些 類庫文件,無需手工配置了。 定義切面Aspect:在啓用@AspectJ 支持的情況下,在application context 中定義的任意帶有一個@Aspect 切面(擁有@Aspect 標註)的bean 都將被Spring 自動識別並用於 配置在Spring AOP。 定義切入點Pointcut:現在通過在 @AspectJ 標註風格的 AOP 中,一個切入點簽名 通過一個普通的方法定義來提供,並且切入點表達式使用 @Pointcut 標註來表示(作爲切 入點簽名的方法必須返回 void 類型)。代碼可以參考清單10.12。 好了,引用了這麼些文檔,我們需要介紹這個基於標註的新的AOP項目了,這個項目 的名字是Spring2_0AOPAspectJ,如前一節所示加入了Spring核心和AOP類庫後,就可以 開發了。那麼相比較10.4.1 使用aop 標籤實現AOP一節,這一個項目的代碼僅僅有兩個地 方要改。首先我們要修改FBI類的源碼,加入標註來實現切面和切入點定義,如下所示: import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; /** * 聯邦調查局的探員將您的所有行動都記錄在案。 * @author BeanSoft */ @Aspect public class FBI { @Before("execution(* Man.*(..))") public void before(JoinPoint point){ Man man = (Man)point.getTarget(); System.err.println("FBI 發現" + man.getName() + "正在進行 " + point.getSignature().getName() + " 活動。"); } } 清單10.12 加入了Aspect 標註的FBI 類 這個類中的@Before 後面的"execution(* Man.*(..))"是切入點所對應的切入點點表達式,其意 義和上一節的是一致的,仍然表示的是執行 Man 類的所有方法時將觸發此方法的執行。 使用了這種寫法後,XML 配置文件將大大簡化,其內容如下所示: <?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" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"> <aop:aspectj-autoproxy/><bean id="fbi" class="FBI" /> <bean id="man" class="Man"> <property name="name"> <value type="java.lang.String">張三</value> </property> </bean> </beans> 1. 加入了粗斜體的<aop:aspectj-autoproxy/>定義; 2. 去掉了<aop:config>標籤部分。 可以看到使用這種方式後,AOP 的開發和配置變的極其簡單。這就是JDK 1.5 引入標註開 發後帶來的好處。當然弱點嘛,那就是要修改配置必須重新編譯源代碼了。 注意:在這裏你不能去掉<bean id="fbi" class="FBI" />這一個bean的定義,否 則自動AOP代理對象就沒有機會被創建並工作了,那樣的話man對象被代理也就無從談起 了。 四開發環繞通知(Around Advice)AOP 應用 @Aspect public class FBI { @Around("execution(* Man.*(..))") public Object before(ProceedingJoinPoint point) throws Throwable { Man man = (Man)point.getTarget(); System.err.println("FBI 發現" + man.getName() + "即將正在進行 " + point.getSignature().getName() + " 活動。"); // 禁止張三泡MM if(point.getSignature().getName().equals("mm")) { System.err.println("FBI 將阻止 " + man.getName() + " 泡MM。"); } else if(point.getSignature().getName().equals("sayHelp")) { System.err.println("FBI 將欺騙 " + man.getName() + " 的朋友告 訴他們他很好。"); return "我是 " + man.getName() + " ,我現在過的很好。"; } else {Object object = point.proceed(); System.err.println("FBI 發現" + man.getName() + "已經完成了 " + point.getSignature().getName() + " 活動。"); return object; } return null; } } 現在張三不光是不能泡MM 了,當他求救的時候,FBI 還可以直接攔截並修改,將其請求的 信息“救我,我是張三!”改成“我是張三,我現在過的很好。”,這樣通過欺騙行爲,張三 的朋友永遠也不知道發生了什麼事。 /** * 具有聊QQ和泡MM以及求救三個行爲的人對象,還有一個用戶名屬性。 * @author BeanSoft */ public class Man { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public void qq() { System.out.println("我在聊QQ"); } public void mm() { System.out.println("我在泡MM"); } public String sayHelp() { return "救我,我是" + getName(); } }
背景 spring和mybatis集成過程中,我們可以通過MapperFactoryBean的方式配置Mapper接口。但是這樣需要在配置文件中,爲每個mapper配置相同的代碼塊,浪費時間。關鍵對於代碼潔癖的人來說,一點不能忍。 <bea
爲什麼要研究字符串? 人機交互的過程中,文字、數字、字母、符號都是字符表現形式,這部分內容佔了人機信息交互的大部分內容,所以有必要明確一些基本問題。因此大部分數據類型都應該有字符串表達形式,我們在定義新類型的時候可以根據需要來定義新類型的
security的簡單原理: 使用衆多的攔截器對url攔截,以此來管理權限。但是這麼多攔截器,不可能對其一一來講,主要講裏面核心流程的兩個。 首先,權限管理離不開登陸驗證的,所以登陸驗證攔截器AuthenticationProcessing
我們經常會需要啓動多個實例的情況來測試註冊中心、配置中心等基礎設施的高可用,也會用來測試客戶端負載均衡的調用等。但是,我們一個應用只能有一個端口號,這就使得在本機測試的時候,不得不爲同一個服務設置不同的端口來進行啓動。 在本地用不同端口啓動
簡介 Java Reflection,稱爲 Java 反射,是Java基礎部分的一個比較難的點。Reflection(反射)是被視爲動態語言的關鍵,通過反射機制,我們可以在運行時(runtime)獲取類的完整結構。例如,可以獲取到
一面 1. 簡短自我介紹 2. 事務的ACID,其中把事務的隔離性詳細解釋一遍 3. 髒讀、幻影讀、不可重複讀 4. 紅黑樹、二叉樹的算法 5. 平常用到哪些集合類?ArrayList和LinkedList區別?HashMap內部數據結構
當我們站在技術之路的原點,未來可能充滿了迷茫,也存在着很多不同的可能。在這個知識爆炸與終身學習/碎片化學習爲主的時代,我們面臨的問題之一就是如何進行有效學習,不僅能有效平衡廣度與深度,並且能真正的積澱下來,提升自己的研發效能。於筆者而
阿里巴巴Java開發手冊 梳理筆記 - finally 塊必須對資源對象、流對象進行關閉 規約內容: 2.1 異常處理 6. 【強制】 finally 塊必須對資源對象、流對象進行關閉,有異常也要做 try - catch 。 說明:如果
在Java方面,能夠實現多線程安全修改對象值得方法只有2個 1.原子操作 2.互斥方法 而在Java當中,或是其他語言中,基本上也都是使用CAS實現。CAS是比較並交換的意思,這個操作包含2個連續的操作,比較,還有賦值,因爲2個操作在cpu
單線程輪詢並執行任務,有可能會導致飢餓。比較適合於一些具有一個任務的週期調度。 任務列表用數組存儲,元素最前面的元素是最先被執行的任務。 schedule方法是固定間隔執行,根據上一次執行的結束時間來定義間隔的開始時間 scheduleAt
創建的ReadWriteLock需要使用兩個方法來繼續創造2個對象,分別是ReadLock和WriteLock。 這兩個鎖對象的方法調用都會匯聚到ReadWriteLock的Sync類中。多個對象的方法調用匯聚到一個對象上面,這個設計模式是
synchronized關鍵字可以修飾普通方法,靜態方法,當修飾普通方法,鎖對象是當前對象,當修飾靜態方法,鎖對象是當前類的class synchroinzed關鍵字可以使用同步代碼塊實現同步,此時可以指定鎖對象。 同步方法的實現方式 同步
AQS是Java多線程編程的重入鎖,管程,工具類的基礎類,是必須要掌握的。不掌握這個類,根本不能稱之爲合格的Java程序員。 即使是把這個類所有的代碼都背會,也是值得的。 如何標識已經有線程在執行呢? 有兩個變量,一個state變量,一個e
################這是之前的思考 內存屏障只是保證清空流水線,如何保證高速緩存的內容更新到最新或刷新到主存呢?這個問題突然想到了,不知道這個需要怎回答。 內存屏障保證的CPU執行執行序列能夠順序執行,而不是亂序執行。當然,前提
使用volidate關鍵字修飾的成員變量,保證可見性,也就是當一個線程修改這樣的成員變量後,其他的線程能夠立即看到這次的修改。有兩個方面的原因: 1.編譯器不優化對這樣的關鍵字修飾變量的一些訪問操作 2.對讀,寫這個關鍵字修飾的變量前後,會