JAVA Spring AspectJ的两种声明式(基于xml、基于注解)

AspectJ:基于JAVA语言 的AOP框架,提供了强大的AOP功能

需要用到的jar包

 

1.基于xml的声明式AspectJ(配置较多)

所有的切面、切入点、通知都必须定义在<aop:config>元素内。下图灰色部分为常用的配置元素:

 

 

                                     图片来源于www.itheima.com

创建接口UserDao:

package cn.edu.gues.jdkAOP;

 

public interface UserDao {

public void addUser();

public void deleteUser();

}

 

 

创建userDaoImpl类,实现userDao接口:

package cn.edu.gues.jdkAOP;

 

public class UserDaoImpl implements UserDao {

//目标类

@Override

public void addUser() {

System.out.println("添加用户");

 

}

 

@Override

public void deleteUser() {

System.out.println("删除用户");

 

}

 

}

 

创建切面类MyAspect:

package cn.edu.aspectj.xml;

 

import org.aspectj.lang.JoinPoint;

import org.aspectj.lang.ProceedingJoinPoint;

 

//切面类,在此类中编写通知

public class MyAspect {

//前置通知

public void myBefore(JoinPoint joinPoint){

System.out.print("前置通知模拟执行权限检查...,");

System.out.print("目标类是:"+joinPoint.getTarget());

System.out.println(",被织入增强处理的目标方法为:"+joinPoint.getSignature().getName());

}

//后置通知

public void myAfterReturning(JoinPoint joinPoint){

System.out.print("后置通知模拟记录日志...,");

System.out.println("被植入增强处理的目标方法为:"+joinPoint.getSignature().getName());

}

/**

 * 环绕通知

 * ProceedingJoinPoint是JoinPoint的子接口,表示可以执行目标方法

 * 1.必须是Object类型的返回值

 * 2.必须接受一个参数,类型为ProceedingJoinPoint

 * 3.必须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(){

System.out.println("最终通知:模拟方法结束后释放资源...");

}

}

创建applicationContext.xml配置文件:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

   xmlns:aop="http://www.springframework.org/schema/aop"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    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="cn.edu.gues.jdkAOP.UserDaoImpl"></bean>

     <!-- 2.切面 -->

     <bean id="myAspect" class="cn.edu.aspectj.xml.MyAspect"></bean>

     <!-- 3.AOP编程 -->

     <aop:config>

      <!-- 配置切面 -->

      <aop:aspect ref="myAspect">

      <!-- 3.1配置切入点,通知最后增强哪些方法 -->

      <aop:pointcut expression="execution(* cn.edu.gues.jdkAOP.*.*(..))" id="myPonitCut"/>

      <!-- 3.2关联通知Advice和切入点pointCut -->

      <!-- 3.2.1配置前置通知 -->

      <aop:before method="myBefore" pointcut-ref="myPonitCut"/>

      <!-- 3.2.1配置前后置通知,在方法返回后执行,就可以获得返回值

      returning属性用于设置后置通知的第二个参数的名称,类型是Object -->

      <aop:after-returning method="myAfterReturning" pointcut-ref="myPonitCut" returning="returnVal"/>

      <!-- 3.2.3环绕通知 -->

      <aop:around method="MyAround" pointcut-ref="myPonitCut"/>

      <!-- 3.2.4抛出异常通知,用于处理程序发生异常 -->

      <!-- *注意:如果程序没有异常,将不会执行增强 -->

      <!-- *throwing属性用于设置通知第二个参数名称,类型Throwable-->

      <aop:after-throwing method="myAfterThrowing" pointcut-ref="myPonitCut" throwing="e"/>

      <!-- 3.2.5最终通知,无论程序发生任何事情,都将执行增强-->

      <aop:after method="myAfter" pointcut-ref="myPonitCut"/>

      </aop:aspect>

     

     </aop:config>

       

 

 </beans>

创建测试类TestXmlAspectJ:

package cn.edu.aspectj.xml;

 

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

 

import cn.edu.gues.jdkAOP.UserDao;

 

public class TestXmlAspectJ {

 

public static void main(String[] args) {

String xmlpath="cn/edu/aspectj/xml/applicationContext.xml";

ApplicationContext applicationContext=new ClassPathXmlApplicationContext(xmlpath);

//1.从spring容器中获得内容

UserDao userDao=(UserDao) applicationContext.getBean("userDao");

//2.执行方法

userDao.addUser();

}

 

}

运行结果图:

 

  1. 基于注解的声明式AppectJ

 

                                            图片来源于www.itheima.com

参照上面的xml的方式,先给UerDaoImpl加上注解

import org.springframework.stereotype.Repository;

 

@Repository("userDao")

public class UserDaoImpl implements UserDao {

//目标类

@Override

public void addUser() {

System.out.println("添加用户");

 

}

 

@Override

public void deleteUser() {

System.out.println("删除用户");

 

}

 

}

 

将之前的myAspect加上相应的注解

package cn.edu.aspectj.annotation;

 

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

@Component

public class MyAspect {

 

//定义切入点表达式

@Pointcut("execution(* cn.edu.gues.jdkAOP.*.*(..))")

//使用一个返回值为void,方法体为空的方法来命名切入点

private void myPointCut(){}

 

//前置通知

@Before("myPointCut()")

public void myBefore(JoinPoint joinPoint){

System.out.print("前置通知模拟执行权限检查...,");

System.out.print("目标类是:"+joinPoint.getTarget());

System.out.println(",被织入增强处理的目标方法为:"+joinPoint.getSignature().getName());

}

//后置通知

@AfterReturning(value="myPointCut()")

public void myAfterReturning(JoinPoint joinPoint){

System.out.print("后置通知模拟记录日志...,");

System.out.println("被植入增强处理的目标方法为:"+joinPoint.getSignature().getName());

}

/**

 * 环绕通知

 * ProceedingJoinPoint是JoinPoint的子接口,表示可以执行目标方法

 * 1.必须是Object类型的返回值

 * 2.必须接受一个参数,类型为ProceedingJoinPoint

 * 3.必须throws Throwable

 * **/

@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(){

System.out.println("最终通知:模拟方法结束后释放资源...");

}

}

 

创建applicationContext配置文件:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

   xmlns:aop="http://www.springframework.org/schema/aop"

   xmlns:context="http://www.springframework.org/schema/context"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    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">

<!-- 指定需要扫描的包,使注解生效 -->

<context:component-scan base-package="cn.edu" />

<!-- 启动基于注解的声明式AspectJ的支持 -->

<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

 

       

 

 </beans>

编写测试类TestAnnotationAspectJ:

package cn.edu.aspectj.annotation;

 

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import org.springframework.stereotype.Repository;

 

import cn.edu.gues.jdkAOP.UserDao;

 

public class TestAnnotationAspectJ {

 

public static void main(String[] args) {

String xmlpath="cn/edu/aspectj/annotation/applicationContext.xml";

ApplicationContext applicationContext=new ClassPathXmlApplicationContext(xmlpath);

//1.从spring容器获得内容,xml文件中虽没有Bean,但是在UserDao中已经注解@Repository("userDao"),xml配置contex即可扫描到bean

UserDao userDao=(UserDao) applicationContext.getBean("userDao");

//2.执行方法

userDao.addUser();

 

}

 

}

运行结果图:

 

相较于xml的方式,注解方式更简便,需要注意的是在导入aspectjweaver-1.8.7.jar包的时候要注意版本与JDK版本对应的问题,否则可能会出现异常。

本博客仅供个人学习,请勿用于商业用途。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值