spring的AOP(五)—-Spring AOP 编程(AspectJ )详解编程语言

AspectJ 简介
AspectJ是一个面向切面的框架,它扩展了Java语言。AspectJ定义了AOP语法所以它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件。
AspectJ是一个基于Java语言的AOP框架
Spring2.0以后新增了对AspectJ切点表达式支持
@AspectJ 是AspectJ1.5新增功能,通过JDK5注解技术,允许直接在Bean类中定义切面
新版本Spring框架,建议使用AspectJ方式来开发AOP
使用AspectJ 需要导入Spring AOP和 AspectJ相关jar包
spring-aop-3.2.0.RELEASE.jar
com.springsource.org.aopalliance-1.0.0.jar
spring-aspects-3.2.0.RELEASE.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

在配置文件中,引入 aop 的schema约束

<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.xsd 
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> 
 
</beans> 

AspectJ 框架定义 Advice 增强类型 (六种 )
AspectJ 在传统AOP 的advice类型基础上,扩展了一种新的类型
1.Before 前置通知,相当于BeforeAdvice
2.AfterReturning 后置通知,相当于AfterReturningAdvice
3.Around 环绕通知,相当于MethodInterceptor
4.AfterThrowing 抛出通知,相当于ThrowAdvice
5.After 最终final通知,不管是否异常,该通知都会执行,这种增强是 AOP联盟规范中不存在的 。在异常发生时,后置通知 无法执行,因为后置通知在方法返回之后,才能执行 ,发生异常,方法无法返回 。最终通知,相当于代码 finally 代码块,目标方法有没有错误,必须执行
6.DeclareParents 引介通知,相当于IntroductionInterceptor

所有AspectJ 增强,内部都可以传入 JoinPoint 连接点对象,通过该对象 可以获得拦截了哪个类哪个方法

代码示例:
OrderDao.java

package com.my.aspectj; 
 
//订单接口 
public interface OrderDao { 
 
    public int save(); 
    public void update(); 
    public void delete(); 
    public void search(); 
 
} 

OrderDaoImpl.java

package com.my.aspectj; 
 
//被代理目标对象 
public class OrderDaoImpl implements OrderDao { 
 
    @Override 
    public int save() { 
        System.out.println("添加订单"); 
        return 10; 
    } 
 
    @Override 
    public void update() { 
        System.out.println("更新订单"); 
    } 
 
    @Override 
    public void delete() { 
        System.out.println("删除订单"); 
        int d = 1/0; 
    } 
 
    @Override 
    public void search() { 
        System.out.println("查询订单"); 
    } 
 
} 

MyAspect.java

package com.my.aspectj; 
 
import org.aspectj.lang.JoinPoint; 
import org.aspectj.lang.ProceedingJoinPoint; 
 
//自定义 切面类 (在切面类当中 定义增强的方法) 
public class MyAspect { 
 
    // 前置增强  
    public void before(JoinPoint joinPoint){ 
        System.out.println("前置增强 ....." + joinPoint.toShortString()); 
    } 
 
    // 后置增强 
    public void afterReturning(JoinPoint joinPoint, Object returnValue){ 
        System.out.println("后置增强...."+ joinPoint.toShortString() + ", 方法返回值:" + returnValue); 
    } 
 
    // 环绕增强  (控制目标方法执行,该方法具有返回值) 
    // ProceedingJoinPoint对象可以控制目标方法执行 
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{  
        System.out.println("环绕前增强...."); 
        Object result = proceedingJoinPoint.proceed(); 
        System.out.println("环绕后增强...."); 
        return null;  
    } 
 
    // 抛出增强 (扑捉目标异常) Throwable对象是固定的 
    public void afterThrowing(JoinPoint joinPoint, Throwable throwable){ 
        System.out.println(joinPoint.toShortString() + "目标方法出现异常.... 原因:" + throwable.getMessage()); 
    } 
 
    // 最终通知 
    public void after(JoinPoint joinPoint){ 
        System.out.println("最终增强..... 用于释放资源 ...."); 
    } 
 
} 
 

applicationContext.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" 
       xsi:schemaLocation=" 
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> 
 
    <!-- AspectJ AOP 开发案例 --> 
    <!-- 目标对象 --> 
    <bean id="orderDao" class="com.my.aspectj.OrderDaoImpl" /> 
    <!-- 切面对象 --> 
    <bean id="myAspect" class="com.my.aspectj.MyAspect"></bean> 
 
    <!-- 进行AOP配置 --> 
    <!-- 默认 有接口 使用 JDK代理,没有接口 使用 Cglib代理  --> 
    <aop:config proxy-target-class="false"> 
        <!-- 整合AspectJ 框架的切面,含有多个切点和多个通知  --> 
        <aop:aspect ref="myAspect"> <!-- 引用自定义切面类 --> 
            <!-- 定义切点 --> 
            <aop:pointcut expression="execution(* com.my.aspectj.OrderDaoImpl.s*(..))" id="myAspectPointcut1"/> 
            <aop:pointcut expression="execution(* com.my.aspectj.OrderDaoImpl.delete(..))" id="myAspectPointcut2"/> 
            <!-- 定义通知 --> 
            <aop:before method="before" pointcut-ref="myAspectPointcut1"/> 
            <aop:after-returning method="afterReturning" pointcut-ref="myAspectPointcut1" returning="returnValue"/> 
            <aop:around method="around" pointcut-ref="myAspectPointcut1"/> 
            <aop:after-throwing method="afterThrowing" pointcut-ref="myAspectPointcut2" throwing="throwable"/> 
            <aop:after method="after" pointcut-ref="myAspectPointcut2"/> 
        </aop:aspect> 
    </aop:config> 
 
</beans>

Test.java

package com.my.aspectj; 
 
import org.junit.runner.RunWith; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.beans.factory.annotation.Qualifier; 
import org.springframework.test.context.ContextConfiguration; 
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 
 
@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations="classpath:applicationContext.xml") 
public class Test { 
 
    @Autowired 
    @Qualifier("orderDao") 
    private OrderDao orderDao; 
 
    @org.junit.Test 
    public void demo(){ 
        orderDao.search(); 
        orderDao.save(); 
        orderDao.update(); 
        orderDao.delete(); 
    } 
 
 
} 

运行结果:
这里写图片描述

使用注解开发AspectJ 实现 AOP编程
在applicationContext.xml 引入 aop名称名称,加入以下配置开启AspectJ自动代理

<aop:aspectj-autoproxy />

注解的作用:
@AspectJ 提供注解
@Aspect 定义切面
@Before 前置通知
@AfterReturning 后置通知
@Around 环绕通知
@AfterThrowing 异常通知
@After 最终通知
@Pointcut 定义切点

代码示例:
UserService.java

package com.my.annotation_aspectj; 
 
public interface UserService { 
 
    public void save(); 
    public int update(); 
    public void delete(); 
    public void select(); 
 
} 

UserServiceImpl.java

package com.my.annotation_aspectj; 
 
public class UserServiceImpl implements UserService { 
 
    @Override 
    public void save() { 
        System.out.println("添加用户"); 
    } 
 
    @Override 
    public int update() { 
        System.out.println("修改用户"); 
        return 0; 
    } 
 
    @Override 
    public void delete() { 
        System.out.println("删除用户"); 
        int[] arr = {}; 
        System.out.println(arr[0]); 
    } 
 
    @Override 
    public void select() { 
        System.out.println("查询用户"); 
    } 
 
} 

MyAspect.java

package com.my.annotation_aspectj; 
 
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; 
 
//使用注解定义切面信息  
@Aspect  
public class MyAspect { 
 
    // 前置增强  
    @Before(value="execution(* com.my.annotation_aspectj.UserServiceImpl.save(..))") // 这里value可以写切点表达式 或者 切点对象调用 
    public void before(JoinPoint joinPoint){ 
        System.out.println("前置增强...." + joinPoint.toShortString()); 
    } 
 
    // 后置增强 
    // returning 用来指定返回值参数名称 
    @AfterReturning(value="execution(* com.my.annotation_aspectj.UserServiceImpl.update(..))", returning="returnVal") 
    public void afterReturning(JoinPoint joinPoint, Object returnVal){ 
        System.out.println("后置增强...." + joinPoint.toShortString() + ", 方法返回值:" + returnVal); 
    } 
 
    // 环绕增强 
    @Around(value="execution(* com.my.annotation_aspectj.UserServiceImpl.s*(..))") 
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{ 
        System.out.println("环绕前增强..."); 
        Object result = proceedingJoinPoint.proceed(); // 执行目标方法 
        System.out.println("环绕后增强..."); 
        return result; 
    } 
 
    // 抛出增强  
    @AfterThrowing(value="mypointcut()", throwing="throwable") 
    // 使用 throwing 参数,指定异常对象传入参数名称 
    public void afterThrowing(JoinPoint joinPoint , Throwable throwable){ 
        System.out.println(joinPoint.toShortString()+"目标方法发生异常,原因:"+ throwable.getMessage()); 
    } 
 
    // 最终增强 
    @After(value="mypointcut()||mypointcut2()") 
    public void after(JoinPoint joinPoint){ 
        System.out.println("最终增强...."); 
    } 
 
    // 单独定义一个切点 
    @Pointcut(value="execution(* com.my.annotation_aspectj.UserServiceImpl.delete(..))") 
    private void mypointcut(){} // 方法名就是切点名 
 
    @Pointcut(value="execution(* com.my.annotation_aspectj.UserServiceImpl.save(..))") 
    private void mypointcut2(){} 
 
} 

applicationContext.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" 
       xsi:schemaLocation=" 
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> 
 
    <!-- 开启AspectJ自动代理-->    
    <aop:aspectj-autoproxy /> <!-- 自动读取切面类中注解信息,完成切面拦截代理  --> 
 
    <!-- 目标 --> 
    <bean id="userService" class="com.my.annotation_aspectj.UserServiceImpl"/> 
    <!-- 切面 --> 
    <bean id="myAspect" class="com.my.annotation_aspectj.MyAspect"></bean> 
 
</beans>

Test.java

package com.my.annotation_aspectj; 
 
import org.junit.runner.RunWith; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.beans.factory.annotation.Qualifier; 
import org.springframework.test.context.ContextConfiguration; 
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 
 
@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations="classpath:applicationContext.xml") 
public class Test { 
 
    @Autowired 
    @Qualifier("userService") 
    private UserService userService; 
 
    @org.junit.Test 
    public void demo(){ 
        userService.select(); 
        userService.save(); 
        userService.delete(); 
        userService.update(); 
 
    } 
 
 
} 

运行结果:
这里写图片描述

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/12095.html

(0)
上一篇 2021年7月19日
下一篇 2021年7月19日

相关推荐

发表回复

登录后才能评论