spring的aop注解配置(了解)
生活随笔
收集整理的這篇文章主要介紹了
spring的aop注解配置(了解)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
這個演示是屬于XML配置的,咱們Spring AOP還有一種,注解配置,注解這個東西就是代理配置文件的,那接著來看一下,使用注解,怎么來做,那其實步驟還是一樣,包還是剛才的4+2+2,準備目標對象也還是一樣的,準備通知,也是一樣的,然后接下來,在配置文件里面就不一樣了,這個刪掉,上面的留著,看著,咱們Spring day02,咱們再新建一個包,專門演示注解的,e_annotaionaop注解AOP,然后呢,咱們復制一個配置文件過來,然后MyAdvice為了不影響之前的那個,就復制一個過來,看明白啥意思不,然后再打開配置文件,第三步這是使用XML配置,可以干掉了,但是配置目標對象和配置通知對象,還是留在配置文件當中,當然你要面試的話,你可以使用咱們第一節講的,是不是可以使用注解把對象注冊到容器當中,我是為了清爽,配置統一,我就XML配置兩個對象,第三個配置改一下,第三個改一下,開啟使用注解完成注入,然后命名空間還是使用AOP名稱空間,然后這里有一個autoproxy,你看這個名字,你看這個名字你就知道,這是咱們的切面的自動代理,這個開關只要你一打開,那接下來的話,你只要在通知當中,寫注解,就可以完成對目標對象的織入,Advice類名寫錯了,咱們是不是要把這個完整類名拿過來,我剛才配的是之前演示的,現在MyAdvice有兩個,在這里面咱們來看一下,把這個注釋刪掉了
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd "><!-- 準備工作:導入(約束)aop的命名空間 --><!-- 1.配置目標對象 --><bean name="userService" class="com.learn.service.UserServiceImpl"></bean><!-- 2.配置通知對象 --><bean name="myAdvice" class="com.learn.e_annotaionaop.MyAdvice"></bean><!-- 3.開啟使用注解完成注入 --><aop:aspectj-autoproxy></aop:aspectj-autoproxy></beans>
首先使用一個@Aspect,用這個注解來表示,不是表示織入,表示該類是一個通知類,加這個注解,Spring看到了,這個類里面一定放有很多通知,接下來before這個方法,你得告訴Spring它是一個前置通知,你需要使用@Before注解,選包選對了,然后呢,括號,他給你報個錯,啥意思呢,他需要參數,叫啥參數呢,你光加一個before告訴他是前置通知還不行,因為你還得表達出你這個通知要應用到哪去,你光告訴他是通知有毛用啊,他知道你通知要干啥,你得告訴他通知要應用到哪去,那咱們怎么告訴他應用到哪去,什么東西,是不是靠那個切點,是表達式,靠這玩意,告訴他通知打算插入到哪去,那表達式我就不再寫了,復制,粘到這里,execution,括號,放到這里去,這就是指定該方法是前置通知,并指定切入點,那接下來的話,會依次類推了,后置通知就是,@AfterReturning,然后他同樣需要這個表達式,然后環繞通知又是,@Around同樣需要表達式,異常通知叫做@AfterThrowing,也是需要這個切點表達式,然后最后@After,這5個通知,就全配置完了,并且這5個通知,就這注解中,配置這幾個信息,這個信息量是不是和XML的信息量是不是一樣的,剛才給我配置文件說,myAdvice這個對象當中,before方法是不是前置通知,應用到切入點,現在我用注解,你應用到before方法,是前置通知,應用到這個切入點,所以到這注解配置就配完了,就配這么多就夠了,接下來咱們來一個Demo
package com.learn.e_annotaionaop;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;/*** 通知類* 表示該類是一個通知類* @author Leon.Sun**/
@Aspect
public class MyAdvice {/*** 前置通知* 指定該方法是前置通知,并指定切入點*/@Before("execution(* com.learn.service.*ServiceImpl.*(..))")public void before() {System.out.println("這是前置通知!!");}/*** 后置通知*/@AfterReturning("execution(* com.learn.service.*ServiceImpl.*(..))")public void afterReturning() {System.out.println("這是后置通知!!(如果出現異常不會調用)");}/*** 環繞通知* @param pjp* @throws Throwable */@Around("execution(* com.learn.service.*ServiceImpl.*(..))")public Object around(ProceedingJoinPoint pjp) throws Throwable {System.out.println("這是環繞通知之前的部分!!");/*** 調用目標方法*/Object proceed = pjp.proceed();System.out.println("這是環繞通知之后的部分!!");return proceed;}/*** 異常通知*/@AfterThrowing("execution(* com.learn.service.*ServiceImpl.*(..))")public void afterException() {System.out.println("出事啦!出現異常啦!");
// int i = 1/0;}/*** 后置通知*/@After("execution(* com.learn.service.*ServiceImpl.*(..))")public void after() {System.out.println("后置通知(無論是否出現異常 都會調用)");}
}
我們測試一下,復制一個Demo過來,然后在這個Demo當中,配置文件的位置要變一下,重新讀取,這個配置文件的位置,去掉src之前的,然后同樣還是這個方法執行一下
package com.learn.e_annotaionaop;import javax.annotation.Resource;import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import com.learn.service.UserService;@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:com/learn/e_annotaionaop/applicationContext.xml")
public class Demo {/*** 將名為userServiceTarget的對象注入到us變量中*/@Resource(name="userService")private UserService us;@Testpublic void fun1() {us.save(); }
}
package com.learn.service;public class UserServiceImpl implements UserService {@Overridepublic void save() {System.out.println("保存用戶!");
// int i = 1/0;}@Overridepublic void delete() {System.out.println("刪除用戶!");}@Overridepublic void update() {System.out.println("更新用戶!");}@Overridepublic void find() {System.out.println("查找用戶");}}
package com.learn.e_annotaionaop;import javax.annotation.Resource;import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import com.learn.service.UserService;@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:com/learn/e_annotaionaop/applicationContext.xml")
public class Demo {/*** 將名為userServiceTarget的對象注入到us變量中*/@Resource(name="userService")private UserService us;@Testpublic void fun1() {us.save(); }
}
是不是也可以,當然我這里報個錯是因為什么啊,是因為我合理人造了一個異常,我就把這個刪掉
這是環繞通知之前的部分!!
這是前置通知!!
保存用戶!
后置通知(無論是否出現異常 都會調用)
出事啦!出現異常啦!
這樣的話我們使用注解來配置,就完事了,就是這個配置,我賦值這個切點,這樣好像不太科學,我寫一個通知,配置一個切點,雖然切點一樣,這塊的話好像不太好管理,好像每一個都要改,咱們能不能把切點抽取出來,看好怎么做,public,來一個void,來一個pc(),定義一個方法,方法名就叫pc,然后@Pointcut,然后在這里面把切點表達式,粘到這里來,然后下面的before,你想用切點的話,怎么寫呢,MyAdvice點pc方法名括號,看明白啥意思不,這樣寫的意思,就是這個切點找MyAdvice這個類的里面的pc方法,寫這個方法你就知道了,找他們的注解,知道啥意思不,所以這個方法,pc方法不要寫任何參數和任何代碼,就是通過這個方法名來找到這個注解,那這樣的話咱們試一下,就叫這一個就行了,這個前置通知加上就OK,看一下前置通知是OK
package com.learn.e_annotaionaop;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;/*** 通知類* 表示該類是一個通知類* @author Leon.Sun**/
@Aspect
public class MyAdvice {@Pointcut("execution(* com.learn.service.*ServiceImpl.*(..))")public void pc() {}/*** 前置通知* 指定該方法是前置通知,并指定切入點*/@Before("MyAdvice.pc()")public void before() {System.out.println("這是前置通知!!");}/*** 后置通知*/@AfterReturning("execution(* com.learn.service.*ServiceImpl.*(..))")public void afterReturning() {System.out.println("這是后置通知!!(如果出現異常不會調用)");}/*** 環繞通知* @param pjp* @throws Throwable */@Around("execution(* com.learn.service.*ServiceImpl.*(..))")public Object around(ProceedingJoinPoint pjp) throws Throwable {System.out.println("這是環繞通知之前的部分!!");/*** 調用目標方法*/Object proceed = pjp.proceed();System.out.println("這是環繞通知之后的部分!!");return proceed;}/*** 異常通知*/@AfterThrowing("execution(* com.learn.service.*ServiceImpl.*(..))")public void afterException() {System.out.println("出事啦!出現異常啦!");
// int i = 1/0;}/*** 后置通知*/@After("execution(* com.learn.service.*ServiceImpl.*(..))")public void after() {System.out.println("后置通知(無論是否出現異常 都會調用)");}
}
這是環繞通知之前的部分!!
這是前置通知!!
保存用戶!
這是環繞通知之后的部分!!
后置通知(無論是否出現異常 都會調用)
這是后置通知!!(如果出現異常不會調用)
所以這樣的話,你就可以挨個粘貼過去,這樣的話你只要改上面的就比較方便,這是咱們的,這就是咱們的擴展內容,使用注解來完成這個注入
?
超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生總結
以上是生活随笔為你收集整理的spring的aop注解配置(了解)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: spring的aop整理
- 下一篇: spring事务管理-概念部分