AspectJ开发

AspectJ 是基于java语言的AOP框架,它提供了强大的AOP功能。Spring2.0 以后,Spring AOP引入了对AspectJ的支持,并允许直接使用AspectJ进行编程,而AspectJ自身的AOP API也尽量与AspectJ 保持一致。新版本的Spring框架,也建议使用AspectJ来开发AOP。使用AspectJ 实现AOP?️两种方式:一种是基于XML的声明式AspectJ,另一种是基于注解的声明式AspectJ。

一、基于XML的声明式AspectJ

基于XML的声明式AspectJ 是指通过XML文件来定义切面、切入点及通知,所有的切面、切入点和通知都必须定义在<aop:config>元素内。<aop:config>元素及其子元素如图3-7所示

   需要导入

   spring-aspects-4.3.6.RELEASE.jar 包

   aspectjweaver-1.8.10.jar 下载地址 http://www.mvnjar.com/org.aspectj/aspectjweaver/1.8.10/detail.html

   1.创建切片类

 

package com.kangxg.aspect.xml;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
/*
 * 切面类,在此类中编写通知
 */
public class MyAspect {
    //前置通知
    public void myBefore(JoinPoint joinPoint)
    {
          System.out.println("前置通知: 模拟执行 检查权限。。。");
          System.out.println("目标类是:"+joinPoint.getTarget());
          System.out.println(",被植入增强处理的目标方法为:"+joinPoint.getSignature().getName());
    }
    //后置通知
    public void myAfterReturining(JoinPoint joinPoint)
    {
          System.out.println("后置通知: 模拟记录日志。。。");
          
          System.out.println(",被植入增强处理的目标方法为:"+joinPoint.getSignature().getName());
    }
    /*
     * 环绕通知
     * ProceedingJoinPoint 是  JoinPoint 子接口,表示可以执行目标方法
     * 1 必须是Object类型的返回型
     * 2 必须接收一个参数,类型为ProceedingJoinPoint
     * 必须 throws Throwable 
     */
    public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable
    {
          //开始
          System.out.println("环绕开始: 执行目标方法之前,模拟开启事务。。。");
          // 执行当前目标方法
          Object obj = proceedingJoinPoint.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("最终通知: 模拟方法结束后的释放资源。。。");
          
    }
}
需要注意:

环绕同事必须接受一个  ProceedingJoinPoint 的参数,返回值也必须是Object类型,且必须抛出异常。异常通知可传入Throwable类型的参数来输出异常信息
2.创建 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-4.3.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
     <!--1  目标类 -->
     <bean id="userDao" class="com.kangxg.jdk.UserDaoImpl" />
    
     <!-- 2 切面 -->
     <bean id="myAspect" class="com.kangxg.aspect.xml.MyAspect" />
     <!-- 3 aop 编程 -->
     <aop:config >
        <!-- aop 切面 -->
        <aop:aspect ref = "myAspect">
           <!-- 3.1 配置切入点 ,通知最后增强哪些方法 -->
           <aop:pointcut expression="execution(* com.kangxg.jdk.*.*(..))" id="myPointcut"/>
           
           <!-- 3.2 关联通知Advice 和切入点 pointCut -->
           <!-- 3.2.1 前置切入点 -->
           <aop:before method="myBefore" pointcut-ref = "myPointcut"/>
           <!-- 3.2.2 后置通知,在方法返回之后执行,就可以获得返回值 returning属性 :用于设置后置通知的第二个参数的名称,类型是Object-->
           <aop:after-returning method="myAfterReturining" pointcut-ref = "myPointcut" returning ="returnVal"/>
           <!-- 3.2.3 环绕通知 -->
           <aop:around method="myAround" pointcut-ref = "myPointcut"/>
           <!-- 3.2.4 抛出通知:用户处理程序发生异常 -->
           <!-- *  如果程序没有异常,将不会执行增强 -->
           <!-- *  throwing 属性:用于设置通知第二个参数的名称,类型 Throwable -->
           <aop:after-throwing method="myAfterThrowing" pointcut-ref = "myPointcut" throwing ="e" />
           <!-- 3.2.5 最终通知,无论程序发生任何事情,都将执行 -->
           <aop:after method="myAfter" pointcut-ref = "myPointcut"/>
        </aop:aspect>
     </aop:config>

</beans>
   需要注意:
4 7 8 红色标注行代码中,分别引入了AOP的Schema约束,然后在配置文件中分别定义了目标类、切面和AOP配置信息
  AOP 切入点表达式说明

execution(* com.kangxg.jdk.*.*(..)) 
第一个 * 表示的是返回类型,使用* 代表所有类型;com.kangxg.jdk 表示的是需要拦截的包名,后面第二个* 表示的是类名,使用* 代表所有的类;第三个* 表示的是方法名,使用* 表示所有方法;后面(..)表示方法的参数,其中..表示任何参数。需要注意的是第一个个* 与包名之间有一个空格

3. 创建 测试类

package com.kangxg.aspect.xml;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.kangxg.jdk.UserDao;

public class TextXmlAspectj {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        String xmlPath = "com/kangxg/aspect/xml/applicationContext.xml";
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
        //从Spring 容器中获取内容
        UserDao userDao =(UserDao) applicationContext.getBean("userDao");
        //执行方法
        userDao.addUser();
    }

}

   4 debug 运行程序 控制台输出结果

  


    要查看异常通知的执行结果,可以在UserDaoImpl 类的addUser()方法中增加错误代码 如int i = 100/0,重新运行测试类,可以看到异常通知的执行,此时控制台的输出结果:



二 基于注释的生命式Aspect J

1.创建 package com.kangxg.aspect.annotaion 包下的切面类 MyAspect

import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
/*
 * 切面类,在此类中编写通知
 */
@Aspect
@Component
public class MyAspect {
    // 定义切入点表达式
    @Pointcut("execution(* com.kangxg.jdk.*.*(..))")
    // 使用 一个返回值为void ,方法体为空的方法来命名切入点
    private void myPointCut(){}
    
    //前置通知
    @Before("myPointCut()")
    public void myBefore(JoinPoint joinPoint)
    {
          System.out.println("前置通知: 模拟执行 检查权限。。。");
          System.out.println("目标类是:"+joinPoint.getTarget());
          System.out.println(",被植入增强处理的目标方法为:"+joinPoint.getSignature().getName());
    }
    //后置通知
    @AfterReturning(value = "myPointCut()")
    public void myAfterReturining(JoinPoint joinPoint)
    {
          System.out.println("后置通知: 模拟记录日志。。。");
          
          System.out.println(",被植入增强处理的目标方法为:"+joinPoint.getSignature().getName());
    }
    /*
     * 环绕通知
     */
    @Around("myPointCut()")
    public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable
    {
          //开始
          System.out.println("环绕开始: 执行目标方法之前,模拟开启事务。。。");
          // 执行当前目标方法
          Object obj = proceedingJoinPoint.proceed();
          //结束
          System.out.println("环绕开始结束:执行目标方法之后,模拟关闭事务。。。");
          return obj;
    }
    // 异常通知
    @AfterThrowing(value = "myPointCut()",throwing = "e")
    public void myAfterThrowing(JoinPoint joinPoint,Throwable e)
    {
        
          System.out.println("异常通知:出错了"+e.getMessage());
    }
    
    //最终通知
    @After("myPointCut()")
    public void myAfter(JoinPoint joinPoint)
    {
          System.out.println("最终通知: 模拟方法结束后的释放资源。。。");
          
    }
}
首先使用@Aspect 注释定义了切片类,由于该类在Spring中作为组建使用的,所以还需要添加@Componnet 注释才能生效

2 创建配置文件

<?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:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.3.xsd">
        
     <!--1  指定需要扫描的包,使注释生效 -->
     <context:component-scan base-package = "com.kangxg" />
    
     <!-- 2 启动基于注释的声明是Aspect J支持 -->
     <aop:aspectj-autoproxy />
   
</beans>
  

3.创建测试类

package com.kangxg.aspect.annotaion;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.kangxg.jdk.UserDao;

public class TestAnnotation {

    public static void main(String[] args) {
        
        String xmlPath = "com/kangxg/aspect/annotaion/applicationContext.xml";
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
        UserDao userDao =(UserDao) applicationContext.getBean("userDao");
        userDao.addUser();
    }


}
4 debug运行 程序,控制台输出

s

手动设置异常 ,控制台输出


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值