當前位置:首頁 » 數據倉庫 » 如何配置aop
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

如何配置aop

發布時間: 2022-01-12 06:52:50

❶ spring mvc 中怎麼配置aop呢

在 beans 裡面

<aop:config>
<aop:aspect id="TestAspect" ref="aspectBean">
<!--配置com.spring.service包下所有類或介面的所有方法-->
<aop:pointcut id="businessService"
expression="execution(* com.spring.service.*.*(..))" />
<aop:before pointcut-ref="businessService" method="doBefore"/>
<aop:after pointcut-ref="businessService" method="doAfter"/>
<aop:around pointcut-ref="businessService" method="doAround"/>
<aop:after-throwing pointcut-ref="businessService" method="doThrowing" throwing="ex"/>
</aop:aspect>
</aop:config>

<bean id="aspectBean" class="com.spring.aop.TestAspect" />
<bean id="aService" class="com.spring.service.AServiceImpl"></bean>
<bean id="bService" class="com.spring.service.BServiceImpl"></bean>

❷ spring中aop全註解時配置類怎麼寫

先說註解,使用註解配置Spring AOP總體分為兩步,第一步是在xml文件中聲明激活自動掃描組件功能,同時激活自動代理功能(同時在xml中添加一個UserService的普通服務層組件,來測試AOP的註解功能):

<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

<!-- 激活組件掃描功能,在包cn.ysh.studio.spring.aop及其子包下面自動掃描通過註解配置的組件 -->
<context:component-scan base-package="cn.ysh.studio.spring.aop"/>
<!-- 激活自動代理功能 -->
<aop:aspectj-autoproxy proxy-target-class="true"/>

<!-- 用戶服務對象 -->
<bean id="userService" class="cn.ysh.studio.spring.aop.service.UserService" />

</beans>

第二步是為Aspect切面類添加註解:

package cn.ysh.studio.spring.aop.aspect;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

/**
* 系統服務組件Aspect切面Bean
* @author Shenghany
* @date 2013-5-28
*/
//聲明這是一個組件
@Component
//聲明這是一個切面Bean
@Aspect
public class ServiceAspect {

private final static Log log = LogFactory.getLog(ServiceAspect.class);

//配置切入點,該方法無方法體,主要為方便同類中其他方法使用此處配置的切入點
@Pointcut("execution(* cn.ysh.studio.spring.aop.service..*(..))")
public void aspect(){ }

/*
* 配置前置通知,使用在方法aspect()上注冊的切入點
* 同時接受JoinPoint切入點對象,可以沒有該參數
*/
@Before("aspect()")
public void before(JoinPoint joinPoint){
if(log.isInfoEnabled()){
log.info("before " + joinPoint);
}
}

//配置後置通知,使用在方法aspect()上注冊的切入點
@After("aspect()")
public void after(JoinPoint joinPoint){
if(log.isInfoEnabled()){
log.info("after " + joinPoint);
}
}

//配置環繞通知,使用在方法aspect()上注冊的切入點
@Around("aspect()")
public void around(JoinPoint joinPoint){
long start = System.currentTimeMillis();
try {
((ProceedingJoinPoint) joinPoint).proceed();
long end = System.currentTimeMillis();
if(log.isInfoEnabled()){
log.info("around " + joinPoint + " Use time : " + (end - start) + " ms!");
}
} catch (Throwable e) {
long end = System.currentTimeMillis();
if(log.isInfoEnabled()){
log.info("around " + joinPoint + " Use time : " + (end - start) + " ms with exception : " + e.getMessage());
}
}
}

//配置後置返回通知,使用在方法aspect()上注冊的切入點
@AfterReturning("aspect()")
public void afterReturn(JoinPoint joinPoint){
if(log.isInfoEnabled()){
log.info("afterReturn " + joinPoint);
}
}

//配置拋出異常後通知,使用在方法aspect()上注冊的切入點
@AfterThrowing(pointcut="aspect()", throwing="ex")
public void afterThrow(JoinPoint joinPoint, Exception ex){
if(log.isInfoEnabled()){
log.info("afterThrow " + joinPoint + " " + ex.getMessage());
}
}

}

測試代碼:

package cn.ysh.studio.spring.aop;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.;

import cn.ysh.studio.spring.aop.service.UserService;
import cn.ysh.studio.spring.mvc.bean.User;

/**
* Spring AOP測試
* @author Shenghany
* @date 2013-5-28
*/
public class Tester {

private final static Log log = LogFactory.getLog(Tester.class);

public static void main(String[] args) {
//啟動Spring容器
ApplicationContext context = new ("applicationContext.xml");
//獲取service組件
UserService service = (UserService) context.getBean("userService");
//以普通的方式調用UserService對象的三個方法
User user = service.get(1L);
service.save(user);
try {
service.delete(1L);
} catch (Exception e) {
if(log.isWarnEnabled()){
log.warn("Delete user : " + e.getMessage());
}
}
}
}

控制台輸出如下:

INFO [spring.aop.aspect.ServiceAspect:40] before execution(User cn.ysh.studio.spring.aop.service.UserService.get(long))
INFO [spring.aop.service.UserService:19] getUser method . . .
INFO [spring.aop.aspect.ServiceAspect:60] around execution(User cn.ysh.studio.spring.aop.service.UserService.get(long)) Use time : 42 ms!
INFO [spring.aop.aspect.ServiceAspect:48] after execution(User cn.ysh.studio.spring.aop.service.UserService.get(long))
INFO [spring.aop.aspect.ServiceAspect:74] afterReturn execution(User cn.ysh.studio.spring.aop.service.UserService.get(long))
INFO [spring.aop.aspect.ServiceAspect:40] before execution(void cn.ysh.studio.spring.aop.service.UserService.save(User))
INFO [spring.aop.service.UserService:26] saveUser method . . .
INFO [spring.aop.aspect.ServiceAspect:60] around execution(void cn.ysh.studio.spring.aop.service.UserService.save(User)) Use time : 2 ms!
INFO [spring.aop.aspect.ServiceAspect:48] after execution(void cn.ysh.studio.spring.aop.service.UserService.save(User))
INFO [spring.aop.aspect.ServiceAspect:74] afterReturn execution(void cn.ysh.studio.spring.aop.service.UserService.save(User))
INFO [spring.aop.aspect.ServiceAspect:40] before execution(boolean cn.ysh.studio.spring.aop.service.UserService.delete(long))
INFO [spring.aop.service.UserService:32] delete method . . .
INFO [spring.aop.aspect.ServiceAspect:65] around execution(boolean cn.ysh.studio.spring.aop.service.UserService.delete(long)) Use time : 5 ms with exception : spring aop ThrowAdvice演示
INFO [spring.aop.aspect.ServiceAspect:48] after execution(boolean cn.ysh.studio.spring.aop.service.UserService.delete(long))
INFO [spring.aop.aspect.ServiceAspect:74] afterReturn execution(boolean cn.ysh.studio.spring.aop.service.UserService.delete(long))
WARN [studio.spring.aop.Tester:32] Delete user : Null return value from advice does not match primitive return type for: public boolean cn.ysh.studio.spring.aop.service.UserService.delete(long) throws java.lang.Exception

可以看到,正如我們預期的那樣,雖然我們並沒有對UserSerivce類包括其調用方式做任何改變,但是Spring仍然攔截到了其中方法的調用,或許這正是AOP的魔力所在。

再簡單說一下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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">


<!-- 系統服務組件的切面Bean -->
<bean id="serviceAspect" class="cn.ysh.studio.spring.aop.aspect.ServiceAspect"/>
<!-- AOP配置 -->
<aop:config>
<!-- 聲明一個切面,並注入切面Bean,相當於@Aspect -->
<aop:aspect id="simpleAspect" ref="serviceAspect">
<!-- 配置一個切入點,相當於@Pointcut -->
<aop:pointcut expression="execution(* cn.ysh.studio.spring.aop.service..*(..))" id="simplePointcut"/>
<!-- 配置通知,相當於@Before、@After、@AfterReturn、@Around、@AfterThrowing -->
<aop:before pointcut-ref="simplePointcut" method="before"/>
<aop:after pointcut-ref="simplePointcut" method="after"/>
<aop:after-returning pointcut-ref="simplePointcut" method="afterReturn"/>
<aop:after-throwing pointcut-ref="simplePointcut" method="afterThrow" throwing="ex"/>
</aop:aspect>
</aop:config>

</beans>

個人覺得不如註解靈活和強大,你可以不同意這個觀點,但是不知道如下的代碼會不會讓你的想法有所改善:

//配置前置通知,攔截返回值為cn.ysh.studio.spring.mvc.bean.User的方法
@Before("execution(cn.ysh.studio.spring.mvc.bean.User cn.ysh.studio.spring.aop.service..*(..))")
public void beforeReturnUser(JoinPoint joinPoint){
if(log.isInfoEnabled()){
log.info("beforeReturnUser " + joinPoint);
}
}

//配置前置通知,攔截參數為cn.ysh.studio.spring.mvc.bean.User的方法
@Before("execution(* cn.ysh.studio.spring.aop.service..*(cn.ysh.studio.spring.mvc.bean.User))")
public void beforeArgUser(JoinPoint joinPoint){
if(log.isInfoEnabled()){
log.info("beforeArgUser " + joinPoint);
}
}

//配置前置通知,攔截含有long類型參數的方法,並將參數值注入到當前方法的形參id中
@Before("aspect()&&args(id)")
public void beforeArgId(JoinPoint joinPoint, long id){
if(log.isInfoEnabled()){
log.info("beforeArgId " + joinPoint + " ID:" + id);
}
}

附上UserService的代碼(其實很簡單):

package cn.ysh.studio.spring.aop.service;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import cn.ysh.studio.spring.mvc.bean.User;

/**
* 用戶服務模型
* @author Shenghany
* @date 2013-5-28
*/
public class UserService {

private final static Log log = LogFactory.getLog(UserService.class);

public User get(long id){
if(log.isInfoEnabled()){
log.info("getUser method . . .");
}
return new User();
}

public void save(User user){
if(log.isInfoEnabled()){
log.info("saveUser method . . .");
}
}

public boolean delete(long id) throws Exception{
if(log.isInfoEnabled()){
log.info("delete method . . .");
throw new Exception("spring aop ThrowAdvice演示");
}
return false;
}

}

應該說學習Spring AOP有兩個難點,第一點在於理解AOP的理念和相關概念,第二點在於靈活掌握和使用切入點表達式。概念的理解通常不在一朝一夕,慢慢浸泡的時間長了,自然就明白了,下面我們簡單地介紹一下切入點表達式的配置規則吧。

通常情況下,表達式中使用」execution「就可以滿足大部分的要求。表達式格式如下:

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)

modifiers-pattern:方法的操作許可權

ret-type-pattern:返回值

declaring-type-pattern:方法所在的包

name-pattern:方法名

parm-pattern:參數名

throws-pattern:異常

其中,除ret-type-pattern和name-pattern之外,其他都是可選的。上例中,execution(* com.spring.service.*.*(..))表示com.spring.service包下,返回值為任意類型;方法名任意;參數不作限制的所有方法。

最後說一下通知參數

可以通過args來綁定參數,這樣就可以在通知(Advice)中訪問具體參數了。例如,<aop:aspect>配置如下:

<aop:config>
<aop:aspect id="TestAspect" ref="aspectBean">
<aop:pointcut id="businessService"
expression="execution(* com.spring.service.*.*(String,..)) and args(msg,..)" />
<aop:after pointcut-ref="businessService" method="doAfter"/>
</aop:aspect>
</aop:config>上面的代碼args(msg,..)是指將切入點方法上的第一個String類型參數添加到參數名為msg的通知的入參上,這樣就可以直接使用該參數啦。



如何配置spring中事務與aop的先後順序

Spring中的事務是通過aop來實現的,當我們自己寫aop攔截的時候,會遇到跟spring的事務aop執行的先後順序問題,比如說動態切換數據源的問題,如果事務在前,數據源切換在後,會導致數據源切換失效,所以就用到了Order(排序)這個關鍵字.

我們可以通過在@AspectJ的方法中實現org.springframework.core.Ordered 這個介面來定義order的順序,order
的值越小,說明越先被執行。比如代碼如下:

[java]view
plain

  • /**

  • *@authorHuifengWang

  • *aop面向切面編程

  • *

  • */

  • @Component

  • @Aspect

  • {

  • //攔截所有的service操作

  • @Pointcut("execution(*com.hc.shop.*.service.*.*(..))")

  • publicvoidreadMethod(){

  • }//匹配所有的讀取操作

  • @Before("readMethod()")

  • publicvoidonlyReadPre(){

  • DataSourceContextHolder.setDataSourceType(DataSourceType.MYSQL);

  • System.out.println("資料庫切換MYSQL");

  • }

  • @After("readMethod()")

  • publicvoidonlyReadPast(){

  • DataSourceContextHolder.setDataSourceType(DataSourceType.ORACLE);

  • System.out.println("資料庫切換回ORACLE");

  • }

  • @Override

  • publicintgetOrder(){

  • //TODOAuto-generatedmethodstub

  • return1;

  • }

  • }

  • 在事務配置的地方也配置order
    欄位,代碼如下:
  • [html]view
    plain

  • <!--註解方式配置事物-->

  • <tx:annotation-driventransaction-manager="transactionManager"order="2"/>


  • 這樣就實現了我們自己寫的aop在事務介入之前就執行了!
  • 可以防止spring事務的失效。

❹ spring的aop怎樣實現

  • 實現原理

  • 前面在學習代理模式的時候,了解到代理模式分為動態代理和靜態代理。現在我們就以代理模式為基礎先實現我們自己的AOP框架,再來研究Spring的AOP的實現原理。

    先以靜態代理實現,靜態代理關鍵是在代理對象和目標對象實現共同的介面,並且代理對象持有目標對象的引用。

    公共介面代碼:

    通過上面例子,可以發現通過動態代理和發射技術,已經基本實現了AOP的功能,如果我們只需要在方法執行前列印日誌,則可以不實現end()方法,這樣就可以控制列印的時機了。如果我們想讓指定的方法列印日誌,我們只需要在invoke()方法中加一個對method名字的判斷,method的名字可以寫在xml文件中,這樣我們就可以實現以配置文件進行解耦了,這樣我們就實現了一個簡單的spring aop框架。

❺ spring aop 配置 returning 怎麼配置

AOP面向方面編程 advice指定Aspect的作用時機, spring提供了以下的通知類型,對應不同的作用時機: 1前置通知:<aop:before>先執行方面邏輯,再執行目標方法; 2後置通知:<aop:after-returning>先執行目標方法,如果不出現異常,再執行方面邏輯; 3異常通知:<aop:after-throwing>先執行目標方法,如果出現異常,再執行方面邏輯; 4最終通知:<aop:after>先執行目標方法,有無異常都再執行方面邏輯;(類似於finally的作用) 5環繞通知:前置+後置,先執行方面的前一部分,再執行目標方法,最後執行方面的剩餘部分。 純手打,求採納哦

❻ spring怎麼實現aop,攔截器怎麼配置的

你指的是aop:config和mvc:interceptors的區別嗎?簡單的講他們的區別是:aop:config是針對類方法的攔截,適用於所有的java類方法的攔截,包括javase。只需要在applicationContext.xml里設置就行了。mvc:interceptors是針對web請求的攔截,與java.servlet.Filter很類似。通過設置需要攔截的url請求從而攔截請求方法。其他方面兩者都差不多。

❼ spring AOP 配置多個類的方法

expression="execution(* com.clouddrive.baseManage.service.impl..*.*(..)) " 改一下這里啊

❽ spring aop怎麼實現的

先了解AOP的相關術語:
1.通知(Advice):
通知定義了切面是什麼以及何時使用。描述了切面要完成的工作和何時需要執行這個工作。
2.連接點(Joinpoint):
程序能夠應用通知的一個「時機」,這些「時機」就是連接點,例如方法被調用時、異常被拋出時等等。
3.切入點(Pointcut)
通知定義了切面要發生的「故事」和時間,那麼切入點就定義了「故事」發生的地點,例如某個類或方法的名稱,Spring中允許我們方便的用正則表達式來指定
4.切面(Aspect)
通知和切入點共同組成了切面:時間、地點和要發生的「故事」
5.引入(Introction)
引入允許我們向現有的類添加新的方法和屬性(Spring提供了一個方法注入的功能)
6.目標(Target)
即被通知的對象,如果沒有AOP,那麼它的邏輯將要交叉別的事務邏輯,有了AOP之後它可以只關注自己要做的事(AOP讓他做愛做的事)
7.代理(proxy)
應用通知的對象,詳細內容參見設計模式裡面的代理模式
8.織入(Weaving)
把切面應用到目標對象來創建新的代理對象的過程,織入一般發生在如下幾個時機:
(1)編譯時:當一個類文件被編譯時進行織入,這需要特殊的編譯器才可以做的到,例如AspectJ的織入編譯器
(2)類載入時:使用特殊的ClassLoader在目標類被載入到程序之前增強類的位元組代碼
(3)運行時:切面在運行的某個時刻被織入,SpringAOP就是以這種方式織入切面的,原理應該是使用了JDK的動態代理技術

Spring提供了4種實現AOP的方式:
1.經典的基於代理的AOP
2.@AspectJ註解驅動的切面
3.純POJO切面
4.注入式AspectJ切面

首先看經典的基於代理的AOP:
Spring支持五種類型的通知:
Before(前) org.apringframework.aop.MethodBeforeAdvice
After-returning(返回後) org.springframework.aop.AfterReturningAdvice
After-throwing(拋出後) org.springframework.aop.ThrowsAdvice
Arround(周圍) org.aopaliance.intercept.MethodInterceptor
Introction(引入) org.springframework.aop.IntroctionInterceptor

值的說明的是周圍通知,他是由AOP Alliance中的介面定義的而非Spring,周圍通知相當於前通知、返回後通知、拋出後通知的結合(傳說中的完全體?好吧,我看日和看多

了)還有引入通知怎麼玩我還沒搞清楚,等心無雜念的時候玩玩

這東西怎麼玩?這么幾個步驟:
1.創建通知:實現這幾個介面,把其中的方法實現了
2.定義切點和通知者:在Spring配製文件中配置這些信息
3.使用ProxyFactoryBean來生成代理

具體做法。。。大晚上的就舉個睡覺的例子吧:

首先寫一個介面叫Sleepable,這是一個牛X的介面,所有具有睡覺能力的東西都可以實現該介面(不光生物,包括關機選項裡面的休眠)

package test.spring.aop.bean

public interface Sleepable{

void sleep();
}

然後寫一個Human類,他實現了這個介面

package test.spring.aop.bean

public Human implements Sleepable{

/*這人莫非跟寡人差不多?
*除了睡覺睡的比較好之外其餘的什麼也不會做?*/
public void sleep(){
System.out.println("睡覺了!夢中自有顏如玉!");
}

}

好了,這是主角,不過睡覺前後要做些輔助工作的,最基本的是脫穿衣服,失眠的人還要吃安眠葯什麼的,但是這些動作與純粹的睡覺這一「業務邏輯」是不相乾的,如果把

這些代碼全部加入到sleep方法中,是不是有違單一職責呢?,這時候我們就需要AOP了。

編寫一個SleepHelper類,它裡麵包含了睡覺的輔助工作,用AOP術語來說它就應該是通知了,我們需要實現上面的介面

package test.spring.aop.bean;

import java.lang.reflect.Method;

import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;

public class SleepHelper implements MethodBeforeAdvice,AfterReturningAdvice{

public void before(Method mtd, Object[] arg1, Object arg2)
throws Throwable {
System.out.println("通常情況下睡覺之前要脫衣服!");
}

public void afterReturning(Object arg0, Method arg1, Object[] arg2,
Object arg3) throws Throwable {
System.out.println("起床後要先穿衣服!");
}

}

然後在spring配置文件中進行配置:
<bean id="sleepHelper" class="test.spring.aop.bean.SleepHelper">
</bean>

OK!現在創建通知的工作就完成了.

第二步是進行配置,這是很令人蛋疼的操作,尤其是這么熱的天,Spring又把東西的名字起的見鬼的長!它為啥不能像usr這種風格呢?

首先要做的是配置一個切點,據說切點的表示方式在Spring中有好幾種,但是常用的只有兩種:1.使用正則表達式 2.使用AspectJ表達式 AspectJ我不是很熟悉(我也是熟悉

黨 or 精通黨?),我還是習慣用正則表達式

Spring使用org.springframework.aop.support.JdkRegexpMethodPointcut來定義正則表達式切點
<bean id="spleepPointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut">
<property name="pattern" value=".*sleep"/>
</bean>

pattern屬性指定了正則表達式,它匹配所有的sleep方法

切點僅僅是定義了故事發生的地點,還有故事發生的時間以及最重要的故事的內容,就是通知了,我們需要把通知跟切點結合起來,我們要使用的通知者是:
org.springframework.aop.support.DefaultPointcutAdvisor

<bean id="sleepHelperAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="advice" ref="sleepHelper"/>
<property name="pointcut" ref="sleepPointcut"/>
</bean>

切入點和通知都配置完成,接下來該調用ProxyFactoryBean產生代理對象了

<bean id="humanProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="human"/>
<property name="interceptorNames" value="sleepHelperAdvisor" />
<property name="proxyInterfaces" value="test.spring.aop.bean.Sleepable" />
</bean>

ProxyFactoryBean是一個代理,我們可以把它轉換為proxyInterfaces中指定的實現該interface的代理對象:

import org.springframework.aop.framework.ProxyFactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.;

import test.spring.aop.bean.Sleepable;

public class Test {

public static void main(String[] args){
ApplicationContext appCtx = new ("applicationContext.xml");
Sleepable sleeper = (Sleepable)appCtx.getBean("humanProxy");
sleeper.sleep();
}
}

程序運行產生結果:
通常情況下睡覺之前要脫衣服!
睡覺啦~夢中自有顏如玉!
起床後要先穿衣服!

OK!這是我們想要的結果,但是上面這個過程貌似有點復雜,尤其是配置切點跟通知,Spring提供了一種自動代理的功能,能讓切點跟通知自動進行匹配,修改配置文件如下:
<bean id="sleepHelper" class="test.spring.aop.bean.SleepHelper">
</bean>
<bean id="sleepAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice" ref="sleepHelper"/>
<property name="pattern" value=".*sleep"/>
</bean>
<bean id="human" class="test.spring.aop.bean.Human">
</bean>
<bean class="org.springframework.aop.framework.autoproxy."/>

執行程序:
public class Test {

public static void main(String[] args){
ApplicationContext appCtx = new ("applicationContext.xml");
Sleepable sleeper = (Sleepable)appCtx.getBean("human");
sleeper.sleep();
}
}
成功輸出結果跟前面一樣!
只要我們聲明了org.springframework.aop.framework.autoproxy.(我勒個去的,名太長了)就能為方法匹配的bean自動創建代理!

但是這樣還是要有很多工作要做,有更簡單的方式嗎?有!

一種方式是使用AspectJ提供的註解:

package test.mine.spring.bean;

import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class SleepHelper {

public SleepHelper(){

}

@Pointcut("execution(* *.sleep())")
public void sleeppoint(){}

@Before("sleeppoint()")
public void beforeSleep(){
System.out.println("睡覺前要脫衣服!");
}

@AfterReturning("sleeppoint()")
public void afterSleep(){
System.out.println("睡醒了要穿衣服!");
}

}

用@Aspect的註解來標識切面,注意不要把它漏了,否則Spring創建代理的時候會找不到它,@Pointcut註解指定了切點,@Before和@AfterReturning指定了運行時的通知,注

意的是要在註解中傳入切點的名稱

然後我們在Spring配置文件上下點功夫,首先是增加AOP的XML命名空間和聲明相關schema
命名空間:
xmlns:aop="http://www.springframework.org/schema/aop"
schema聲明:
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd

然後加上這個標簽:
<aop:aspectj-autoproxy/> 有了這個Spring就能夠自動掃描被@Aspect標注的切面了

最後是運行,很簡單方便了:
public class Test {

public static void main(String[] args){
ApplicationContext appCtx = new ("applicationContext.xml");
Sleepable human = (Sleepable)appCtx.getBean("human");
human.sleep();
}
}

下面我們來看最後一種常用的實現AOP的方式:使用Spring來定義純粹的POJO切面

前面我們用到了<aop:aspectj-autoproxy/>標簽,Spring在aop的命名空間裡面還提供了其他的配置元素:
<aop:advisor> 定義一個AOP通知者
<aop:after> 後通知
<aop:after-returning> 返回後通知
<aop:after-throwing> 拋出後通知
<aop:around> 周圍通知
<aop:aspect>定義一個切面
<aop:before>前通知
<aop:config>頂級配置元素,類似於<beans>這種東西
<aop:pointcut>定義一個切點

我們用AOP標簽來實現睡覺這個過程:
代碼不變,只是修改配置文件,加入AOP配置即可:
<aop:config>
<aop:aspect ref="sleepHelper">
<aop:before method="beforeSleep" pointcut="execution(* *.sleep(..))"/>
<aop:after method="afterSleep" pointcut="execution(* *.sleep(..))"/>
</aop:aspect>
</aop:config>

完!

❾ spring配置aop的方式有哪些

1. 基於xml配置文件的代理配置方式
這種方式在2.0以後很少用了,原因是配置項過多,過於繁瑣。但對於理解Spring AOP還是很有幫助的
1.1 定義通知
<bean id="advice" class="yourAdviceImpl" />
1.2 定義切點
要定義一個切點,可以選擇使用正則表達式方式聲明的切點或者AspectJ方式聲明的切點。對正則表達式切點,使用Perl5RegexpMethodPointcut或JdkRegexpMethodPointcut(Java
1.4以上版本,不需要Jakarta ORO的支持了);對AspectJ切點,使用AspectJExpressPointcut
<bean id="pointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut">
<property name="pattern" value="yourRegularExpression" />
</bean>
<bean id="pointcut" class="org.springframework.aop.aspectj.AspectJExpressionPointcut">
<property name="expression" value="yourAspectJExpression" />
</bean>
1.3 定義通知者
DefaultPointcutAdvisor是Spring提供的默認通知者,它需要提供通知和切點的引用。
Spring也提供了RegexpMethodPointcutAdvisor和來對應兩種聲明切點的方式,不用再單獨定義切點。
<bean id="advisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="advice" ref="advice" />
<property name="pointcut" ref="pointcut" />
</bean>

<bean id="advisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice" ref="advice" />
<property name="pattern" value="yourRegularExpression" />
</bean>

<bean id="advisor" class="org.springframework.aop.aspectj.AspectJExpressionPointcut">
<property name="advice" ref="advice" />
<property name="expression" value="yourAspectjExpression" />
</bean>

1.4 定義ProxyFactoryBean
<bean id="yourBean" class="org.springframework.aop.framework.ProxyFactoryBean>
<property name="target" ref="yourTargetBean" />
<property name="interceptorNames" value="advisor" />
<property name="proxyInterfaces" value="interfaceClass" />
</bean>
interceptorNames和proxyInterfaces都是數組屬性,所以可以聲明要使用的一個list,也可以讓Spring自動把單個值轉化為數組

上面明確定義了要對那個targetBean應用代理生成切面實例。如果不想限制targetBean,可以讓Spring為所有匹配切點聲明的bean生成切面實例,這樣就不用一個個定義ProxyFactoryBean了,只需要定義
<bean class="org.springframework.aop.framework.autoproxy." />
這是一個BeanPostProcessor,所以Spring會自動識別並在bean的聲明周期使用

2 利用2.0以後使用aop標簽
<aop:config>
<aop:aspect ref="">
<aop:pointcut id="performance" expression="execution(* *.perform(..))" />
<aop:before method="" pointcut-ref="performance" />
<aop:before method="" pointcut="execution(* *.perform(..))" />
<aop:after-returning method="" pointcut="execution(* *.perform(..))" />
<aop:after-throwing method="" pointcut="execution(* *.perform(..))" />
</aop:aspect>
</aop:config>

3 利用Annotation

3.1 利用@Aspect將一個POJO類聲明為一個切面。

3.2 定義切點
@Pointcut("execution(* *.perform(..))")
public void performance(){}
通過@Pointcut定義的切點的名字就是它所註解的方法的名字,因此例子中的切點名字是
performance()。這里聲明的performance()方法實際聖只是一個標記,為@Pointcut提供附加的點,並不要求有實際意義。

3.3 定義通知
對要執行切面的方法,通過@Before("performance()"),@AfterReturning
("performance()")來定義通知。注意這里提供的切點名稱,是performance(),而不是performance

如果對上面的兩點不是很理解,也可以省略@Pointcut,而將AspectJ表達式直接定義在@Before等通知中,將上面的兩步合為一步,如@Before("execution(* *.perform(..))")

3.4 通知Spring創建代理
<aop:aspectj-autoproxy>
這實際上相當於聲明了一個,從而根據@Pointcut聲明的切點來自動代理匹配的bean實例

4 在Spring中結合進AspectJ
對於超出Spring AOP支持范圍的,可以採用這種方式。只需要在Spring中配置AspectJ的Class實例時讓Spring能夠獲得AspectJ類的實例就可以了,比如
<bean class="a_aspectj_class" factory-method="aspectOf">
<preperty .... />
</bean>

❿ springaop怎麼在xml文件中配置

就是首先需要的
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<tx:method name="find*" propagation="SUPPORTS" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut expression="execution(* com.linksky.ssm.service.*.*(..))"
id="txPointcut" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut" />
</aop:config>