java元婴期(20)----java进阶(spring(4)---spring aop编程(全自动)AspectJ)
spring aop編程:全自動(dòng)【掌握】
- 從spring容器獲得目標(biāo)類,如果配置aop,spring將自動(dòng)生成代理。
- 要確定目標(biāo)類,aspectj 切入點(diǎn)表達(dá)式,導(dǎo)入jar包(maven項(xiàng)目直接導(dǎo)入相關(guān)坐標(biāo),可取官網(wǎng)查詢)
spring-framework-3.0.2.RELEASE-dependencies\org.aspectj\com.springsource.org.aspectj.weaver\1.6.8.RELEASE
?
?
spring配置
切記務(wù)必要添加aop的相關(guān)約束
其余部分的代碼均在上一篇可尋!!!!!,此處只寫關(guān)鍵部分
<?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"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"><!-- 1 創(chuàng)建目標(biāo)類 --><bean id="userServiceId" class="com.itheima.c_spring_aop.UserServiceImpl"></bean><!-- 2 創(chuàng)建切面類(通知) --><bean id="myAspectId" class="com.itheima.c_spring_aop.MyAspect"></bean><!-- 3 aop編程 3.1 導(dǎo)入命名空間3.2 使用 <aop:config>進(jìn)行配置proxy-target-class="true" 聲明時(shí)使用cglib代理<aop:pointcut> 切入點(diǎn) ,從目標(biāo)對(duì)象獲得具體方法<aop:advisor> 特殊的切面,只有一個(gè)通知 和 一個(gè)切入點(diǎn)advice-ref 通知引用pointcut-ref 切入點(diǎn)引用3.3 切入點(diǎn)表達(dá)式execution(* com.itheima.c_spring_aop.*.*(..))選擇方法 返回值任意 包 類名任意 方法名任意 參數(shù)任意--><aop:config proxy-target-class="true"><aop:pointcut expression="execution(* com.itheima.c_spring_aop.*.*(..))" id="myPointCut"/><aop:advisor advice-ref="myAspectId" pointcut-ref="myPointCut"/></aop:config> </beans>測試
@Testpublic void demo01(){String xmlPath = "com/itheima/c_spring_aop/beans.xml";ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);//獲得目標(biāo)類UserService userService = (UserService) applicationContext.getBean("userServiceId");userService.addUser();userService.updateUser();userService.deleteUser();}AspectJ
介紹
AspectJ是一個(gè)基于Java語言的AOP框架
Spring2.0以后新增了對(duì)AspectJ切點(diǎn)表達(dá)式支持
@AspectJ 是AspectJ1.5新增功能,通過JDK5注解技術(shù),允許直接在Bean類中定義切面
新版本Spring框架,建議使用AspectJ方式來開發(fā)AOP
主要用途:自定義開發(fā)
切入點(diǎn)表達(dá)式【掌握】
1.execution()? 用于描述方法 【掌握】
?語法:execution(修飾符? 返回值? 包.類.方法名(參數(shù)) throws異常)
| public??????????? ? ? | ? 公共方法 |
| ???? *?????????????????? | 任意 |
???
| ?? void???????? | ??? 返回沒有值 |
| ? String??????? | 返回值字符串 |
| ????? * ? | ???? 任意 |
? ? ? ? ??
| ????? com.itheima.crm?? | ? 固定包 |
| com.itheima.crm.*.service??? | ??? crm包下面子包任意 (例如:com.itheima.crm.staff.service) |
| ?? com.itheima.crm..???????? | ? crm包下面的所有子包(含自己) |
| ???? com.itheima.crm.*.service..?? | crm包下面任意子包,固定目錄service,service目錄任意包 |
???????????????? ? ? ? ? ? ?
| UserServiceImpl???? | 指定類 |
| *Impl???????? | ?以Impl結(jié)尾 |
| User*????? | ?以User開頭 |
| ??? *??? | ?任意 |
??????
| ????? addUser??????? | 固定方法 |
| ????? add*???????????????? | ?以add開頭 |
| ? ? ? *Do?????????????? | ? 以Do結(jié)尾 |
| ? ? ? ? *???? | ? 任意 |
??????
| ? ()?? | ? ?無參 |
| ? (int)? | ?? 一個(gè)整型 |
| ? (int ,int)??? | ?? 兩個(gè) |
| ? (..)?? | ? 參數(shù)任意 |
? throws ,可省略,一般不寫。
綜合1
?????? execution(* com.itheima.crm.*.service..*.*(..))
綜合2
?????? <aop:pointcut expression="execution(* com.itheima.*WithCommit.*(..)) ||
???????????????????????? ?execution(* com.itheima.*Service.*(..))" id="myPointCut"/>
2.within:匹配包或子包中的方法(了解)
?????? within(com.itheima.aop..*)
3.this:匹配實(shí)現(xiàn)接口的代理對(duì)象中的方法(了解)
?????? this(com.itheima.aop.user.UserDAO)
4.target:匹配實(shí)現(xiàn)接口的目標(biāo)對(duì)象中的方法(了解)
?????? target(com.itheima.aop.user.UserDAO)
5.args:匹配參數(shù)格式符合標(biāo)準(zhǔn)的方法(了解)
?????? args(int,int)
6.bean(id)? 對(duì)指定的bean所有的方法(了解)
?????? bean('userServiceId')
AspectJ 通知類型
? ? ? 1. before:前置通知(應(yīng)用:各種校驗(yàn))
????????????? 在方法執(zhí)行前執(zhí)行,如果通知拋出異常,阻止方法運(yùn)行
? ? ? ?2.afterReturning:后置通知(應(yīng)用:常規(guī)數(shù)據(jù)處理)
????????????? 方法正常返回后執(zhí)行,如果方法中拋出異常,通知無法執(zhí)行
????????????? 必須在方法執(zhí)行后才執(zhí)行,所以可以獲得方法的返回值。
????? ?3.around:環(huán)繞通知(應(yīng)用:十分強(qiáng)大,可以做任何事情)
????????????? 方法執(zhí)行前后分別執(zhí)行,可以阻止方法的執(zhí)行
????????????? 必須手動(dòng)執(zhí)行目標(biāo)方法
? ? ? ?4.afterThrowing:拋出異常通知(應(yīng)用:包裝異常信息)
????????????? 方法拋出異常后執(zhí)行,如果方法沒有拋出異常,無法執(zhí)行
? ? ? ?5.after:最終通知(應(yīng)用:清理現(xiàn)場)
????????????? 方法執(zhí)行完畢后執(zhí)行,無論方法中是否出現(xiàn)異常
環(huán)繞try{//前置:before//手動(dòng)執(zhí)行目標(biāo)方法//后置:afterRetruning } catch(){//拋出異常 afterThrowing } finally{//最終 after }導(dǎo)入jar包:
4個(gè):
- ?????? aop聯(lián)盟規(guī)范
- ?????? spring aop 實(shí)現(xiàn)
- ?????? aspect 規(guī)范
- ?????? spring aspect 實(shí)現(xiàn)
基于xml
切面類
/*** 切面類,含有多個(gè)通知*/ public class MyAspect {public void myBefore(JoinPoint joinPoint){System.out.println("前置通知 : " + joinPoint.getSignature().getName());}public void myAfterReturning(JoinPoint joinPoint,Object ret){System.out.println("后置通知 : " + joinPoint.getSignature().getName() + " , -->" + ret);}public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{System.out.println("前");//手動(dòng)執(zhí)行目標(biāo)方法Object obj = joinPoint.proceed();System.out.println("后");return obj;}public void myAfterThrowing(JoinPoint joinPoint,Throwable e){System.out.println("拋出異常通知 : " + e.getMessage());}public void myAfter(JoinPoint joinPoint){System.out.println("最終通知");}}?
?
spring配置
<!-- 1 創(chuàng)建目標(biāo)類 --><bean id="userServiceId" class="com.itheima.d_aspect.a_xml.UserServiceImpl"></bean><!-- 2 創(chuàng)建切面類(通知) --><bean id="myAspectId" class="com.itheima.d_aspect.a_xml.MyAspect"></bean><!-- 3 aop編程 <aop:aspect> 將切面類 聲明“切面”,從而獲得通知(方法)ref 切面類引用<aop:pointcut> 聲明一個(gè)切入點(diǎn),所有的通知都可以使用。expression 切入點(diǎn)表達(dá)式id 名稱,用于其它通知引用--><aop:config><aop:aspect ref="myAspectId"><aop:pointcut expression="execution(* com.itheima.d_aspect.a_xml.UserServiceImpl.*(..))" id="myPointCut"/><!-- 3.1 前置通知 <aop:before method="" pointcut="" pointcut-ref=""/>method : 通知,及方法名pointcut :切入點(diǎn)表達(dá)式,此表達(dá)式只能當(dāng)前通知使用。pointcut-ref : 切入點(diǎn)引用,可以與其他通知共享切入點(diǎn)。通知方法格式:public void myBefore(JoinPoint joinPoint){參數(shù)1:org.aspectj.lang.JoinPoint 用于描述連接點(diǎn)(目標(biāo)方法),獲得目標(biāo)方法名等例如:<aop:before method="myBefore" pointcut-ref="myPointCut"/>--><!-- 3.2后置通知 ,目標(biāo)方法后執(zhí)行,獲得返回值<aop:after-returning method="" pointcut-ref="" returning=""/>returning 通知方法第二個(gè)參數(shù)的名稱通知方法格式:public void myAfterReturning(JoinPoint joinPoint,Object ret){參數(shù)1:連接點(diǎn)描述參數(shù)2:類型Object,參數(shù)名 returning="ret" 配置的例如:<aop:after-returning method="myAfterReturning" pointcut-ref="myPointCut" returning="ret" />--><!-- 3.3 環(huán)繞通知 <aop:around method="" pointcut-ref=""/>通知方法格式:public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{返回值類型:Object方法名:任意參數(shù):org.aspectj.lang.ProceedingJoinPoint拋出異常執(zhí)行目標(biāo)方法:Object obj = joinPoint.proceed();例如:<aop:around method="myAround" pointcut-ref="myPointCut"/>--><!-- 3.4 拋出異常<aop:after-throwing method="" pointcut-ref="" throwing=""/>throwing :通知方法的第二個(gè)參數(shù)名稱通知方法格式:public void myAfterThrowing(JoinPoint joinPoint,Throwable e){參數(shù)1:連接點(diǎn)描述對(duì)象參數(shù)2:獲得異常信息,類型Throwable ,參數(shù)名由throwing="e" 配置例如:<aop:after-throwing method="myAfterThrowing" pointcut-ref="myPointCut" throwing="e"/>--><!-- 3.5 最終通知 --> <aop:after method="myAfter" pointcut-ref="myPointCut"/></aop:aspect></aop:config>?
基于注解
?替換bean
<!-- 1 創(chuàng)建目標(biāo)類 --><bean id="userServiceId" class="com.itheima.d_aspect.b_anno.UserServiceImpl"></bean><!-- 2 創(chuàng)建切面類(通知) --><bean id="myAspectId" class="com.itheima.d_aspect.b_anno.MyAspect"></bean>替換后
注意:掃描
<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/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 1.掃描 注解類 --><context:component-scan base-package="com.itheima.d_aspect.b_anno"></context:component-scan>替換aop
必須進(jìn)行aspectj 自動(dòng)代理
<!-- 2.確定 aop注解生效 --><aop:aspectj-autoproxy></aop:aspectj-autoproxy>聲明切面
<aop:aspect ref="myAspectId">替換前置通知
<aop:before method="myBefore" pointcut="execution(* com.itheima.d_aspect.b_anno.UserServiceImpl.*(..))"/>替換后
@Before("execution(* com.itheima.d_aspect.b_anno.UserServiceImpl.*(..))")public void myBefore(JoinPoint joinPoint){System.out.println("前置通知 : " + joinPoint.getSignature().getName());}替換 公共切入點(diǎn)
<aop:pointcut expression="execution(* com.itheima.d_aspect.b_anno.UserServiceImpl.*(..))" id="myPointCut"/>替換后
@Pointcut("execution(* com.itheima.d_aspect.b_anno.UserServiceImpl.*(..))")private void myPointCut(){}替換后置
<aop:after-returning method="myAfterReturning" pointcut-ref="myPointCut" returning="ret" />替換后
@AfterReturning(value="myPointCut()" ,returning="ret")public void myAfterReturning(JoinPoint joinPoint,Object ret){System.out.println("后置通知 : " + joinPoint.getSignature().getName() + " , -->" + ret);}替換環(huán)繞
<aop:around method="myAround" pointcut-ref="myPointCut"/>替換后
@Around(value = "myPointCut()")public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{System.out.println("前");//手動(dòng)執(zhí)行目標(biāo)方法Object obj = joinPoint.proceed();System.out.println("后");return obj;}替換拋出異常
<aop:after-throwing method="myAfterThrowing" pointcut="execution(* com.itheima.d_aspect.b_anno.UserServiceImpl.*(..))" throwing="e"/>替換后
@AfterThrowing(value="execution(* com.itheima.d_aspect.b_anno.UserServiceImpl.*(..))" ,throwing="e")public void myAfterThrowing(JoinPoint joinPoint,Throwable e){System.out.println("拋出異常通知 : " + e.getMessage());}切面類
/*** 切面類,含有多個(gè)通知*/ @Component @Aspect public class MyAspect {//切入點(diǎn)當(dāng)前有效 // @Before("execution(* com.itheima.d_aspect.b_anno.UserServiceImpl.*(..))")public void myBefore(JoinPoint joinPoint){System.out.println("前置通知 : " + joinPoint.getSignature().getName());}//聲明公共切入點(diǎn)@Pointcut("execution(* com.itheima.d_aspect.b_anno.UserServiceImpl.*(..))")private void myPointCut(){}// @AfterReturning(value="myPointCut()" ,returning="ret")public void myAfterReturning(JoinPoint joinPoint,Object ret){System.out.println("后置通知 : " + joinPoint.getSignature().getName() + " , -->" + ret);}// @Around(value = "myPointCut()")public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{System.out.println("前");//手動(dòng)執(zhí)行目標(biāo)方法Object obj = joinPoint.proceed();System.out.println("后");return obj;}// @AfterThrowing(value="execution(* com.itheima.d_aspect.b_anno.UserServiceImpl.*(..))" ,throwing="e")public void myAfterThrowing(JoinPoint joinPoint,Throwable e){System.out.println("拋出異常通知 : " + e.getMessage());}@After("myPointCut()")public void myAfter(JoinPoint joinPoint){System.out.println("最終通知");}}?
spring配置
<!-- 1.掃描 注解類 --><context:component-scan base-package="com.itheima.d_aspect.b_anno"></context:component-scan><!-- 2.確定 aop注解生效 --><aop:aspectj-autoproxy></aop:aspectj-autoproxy>?
aop注解總結(jié)?
@Aspect? 聲明切面,修飾切面類,從而獲得 通知。
通知
- ?????? @Before 前置
- ?????? @AfterReturning 后置
- ?????? @Around 環(huán)繞
- ?????? @AfterThrowing 拋出異常
- ?????? @After 最終
切入點(diǎn)
@PointCut ,修飾方法 private void xxx(){}? 之后通過“方法名”獲得切入點(diǎn)引用
總結(jié)
以上是生活随笔為你收集整理的java元婴期(20)----java进阶(spring(4)---spring aop编程(全自动)AspectJ)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java元婴期(19)----java进
- 下一篇: java元婴期(21)----java进