Spring基础(十一):AOP注解和XML方式实现
【摘要】
文章目录
AOP注解和XML方式实现
一、注解方式实现
1、准备工作
2、准备接口
3、接口实现类
4、准备切面
5、测试代码
6、概念补充
7、完全使用注解开发
二、XML配置方式实现
1、创建两个类,增强类和被增强类,创建方法
2、在spring配置文件中创建两个类对象
3、在spring配置文件中配置...
文章目录
AOP注解和XML方式实现
注意:AspectJ本身并不是spring框架中的组成部分, 是一个独立的AOP框架,一般把AspectJ和Spring框架的AOP依赖一起使用,所以要导入一个独立的依赖
实现的两种方式
1、基于注解方式实现 (熟练)
2、基于XML配置方式 (了解)
一、注解方式实现
1、准备工作
导入依赖
-
<dependencies>
-
<!--spring核心容器包-->
-
<dependency>
-
<groupId>org.springframework</groupId>
-
<artifactId>spring-context</artifactId>
-
<version>5.3.5</version>
-
</dependency>
-
<!--spring切面包-->
-
<dependency>
-
<groupId>org.springframework</groupId>
-
<artifactId>spring-aspects</artifactId>
-
<version>5.3.5</version>
-
</dependency>
-
<!--织入包 spring-aspects 已经导入该包,这里可以不导入-->
-
<!--<dependency>
-
<groupId>org.aspectj</groupId>
-
<artifactId>aspectjweaver</artifactId>
-
<version>1.9.6</version>
-
</dependency>-->
-
<!--aop联盟包-->
-
<dependency>
-
<groupId>aopalliance</groupId>
-
<artifactId>aopalliance</artifactId>
-
<version>1.0</version>
-
</dependency>
-
<!--Apache Commons日志包-->
-
<dependency>
-
<groupId>commons-logging</groupId>
-
<artifactId>commons-logging</artifactId>
-
<version>1.2</version>
-
</dependency>
-
<!--德鲁伊连接池-->
-
<dependency>
-
<groupId>com.alibaba</groupId>
-
<artifactId>druid</artifactId>
-
<version>1.1.10</version>
-
</dependency>
-
<!--mysql驱动-->
-
<dependency>
-
<groupId>mysql</groupId>
-
<artifactId>mysql-connector-java</artifactId>
-
<version>8.0.22</version>
-
</dependency>
-
<!--Junit单元测试-->
-
<dependency>
-
<groupId>junit</groupId>
-
<artifactId>junit</artifactId>
-
<version>4.13.1</version>
-
<scope>test</scope>
-
</dependency>
-
<!--lombok -->
-
<dependency>
-
<groupId>org.projectlombok</groupId>
-
<artifactId>lombok</artifactId>
-
<version>1.18.12</version>
-
<scope>provided</scope>
-
</dependency>
-
</dependencies>
切入点表达式:通过一个表达式来确定AOP要增强的是哪个或者那些方法
语法结构:execution([权限修饰符][返回值类型][类的全路径名][方法名](参数 列表) )
例子1
-
execution(* com.lanson.dao.UserDaoImpl.add(..)) //指定切点为UserDaoImpl.add方法
-
-
execution(* com.lanson.dao.UserDaoImpl.*(..)) //指定切点为UserDaoImpl.所有的方法
-
-
execution(* com.lanson.dao.*.*(..)) //指定切点为dao包下所有的类中的所有的方法
-
-
execution(* com.lanson.dao.*.add(..)) // 指定切点为dao包下所有的类中的add的方法
-
-
execution(* com.lanson.dao.*.add*(..)) // 指定切点为dao包下所有的类中的add开头的方法
基于注解方式实现
项目结构
开启注解扫描和AOP切面编程自动生成代理对象配置
-
<?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:p="http://www.springframework.org/schema/p"
-
xmlns:c="http://www.springframework.org/schema/c"
-
xmlns:util="http://www.springframework.org/schema/util"
-
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.xsd
-
http://www.springframework.org/schema/util
-
http://www.springframework.org/schema/util/spring-util.xsd
-
http://www.springframework.org/schema/context
-
http://www.springframework.org/schema/context/spring-context.xsd
-
http://www.springframework.org/schema/aop
-
http://www.springframework.org/schema/aop/spring-aop.xsd
-
">
-
<!--spring 包扫描 -->
-
<context:component-scan base-package="com.lanson"/>
-
<!--aop autoProxy 自动生成代理对象 -->
-
<aop:aspectj-autoproxy/>
-
</beans>
2、准备接口
UserDao和EmpDao
-
package com.lanson.dao;
-
/**
-
* @Author: Lansonli
-
* @Description: MircoMessage:Mark_7001
-
*/
-
public interface EmpDao {
-
int addEmp(Integer empno,String ename,String job);
-
}
-
package com.lanson.dao;
-
/**
-
* @Author: Lansonli
-
* @Description: MircoMessage:Mark_7001
-
*/
-
public interface UserDao {
-
int addUser(Integer userid,String username);
-
}
3、接口实现类
-
package com.lanson.dao.impl;
-
import com.lanson.dao.UserDao;
-
import org.springframework.stereotype.Repository;
-
/**
-
* @Author: Lansonli
-
* @Description: MircoMessage:Mark_7001
-
*/
-
@Repository
-
public class UserDaoImpl implements UserDao {
-
public int addUser(Integer userid,String username){
-
System.out.println("userdao add ... ...");
-
//int i =1/0;
-
return 1;
-
}
-
}
-
package com.lanson.dao.impl;
-
import com.lanson.dao.EmpDao;
-
import com.lanson.dao.UserDao;
-
import org.springframework.stereotype.Repository;
-
/**
-
* @Author: Lansonli
-
* @Description: MircoMessage:Mark_7001
-
*/
-
@Repository
-
public class EmpDaoImpl implements EmpDao {
-
public int addEmp(Integer empno,String ename,String job){
-
System.out.println("empDao add ... ...");
-
return 1;
-
}
-
}
4、准备切面
-
package com.lanson.aspect;
-
import org.aspectj.lang.JoinPoint;
-
import org.aspectj.lang.ProceedingJoinPoint;
-
import org.aspectj.lang.annotation.*;
-
import org.springframework.core.annotation.Order;
-
import org.springframework.stereotype.Component;
-
import java.util.Arrays;
-
/**
-
* @Author: Lansonli
-
* @Description: MircoMessage:Mark_7001
-
*/
-
@Component
-
@Aspect
-
public class DaoAspect {
-
//定义公共切点
-
@Pointcut("execution(* com.lanson.dao.*.add*(..))")
-
public void addPointCut(){}
-
/*
-
* 前置通知: 切点方法执行之前先执行的功能
-
* 参数列表可以用JoinPoint接收切点对象
-
* 可以获取方法执行的参数
-
* */
-
@Before("addPointCut()")
-
public void methodBefore(JoinPoint joinPoint){
-
System.out.println("Before invoked");
-
}
-
/*
-
* 后置通知:方法执行之后要增强的功能
-
* 无论切点方法是否出现异常都会执行的方法
-
* 参数列表可以用JoinPoint接收切点对象
-
* */
-
@After("addPointCut()")
-
public void methodAfter(JoinPoint joinPoint){
-
System.out.println("After invoked");
-
}
-
/*
-
* 返回通知:切点方法正常运行结束后增强的功能
-
* 如果方法运行过程中出现异常,则该功能不运行
-
* 参数列表可以用 JoinPoint joinPoint接收切点对象
-
* 可以用Object res接收方法返回值,需要用returning指定返回值名称
-
* */
-
@AfterReturning( value = "addPointCut()",returning = "res")
-
public void methodAfterReturning(JoinPoint joinPoint,Object res){
-
System.out.println("AfterReturning invoked");
-
}
-
/*
-
* 异常通知:切点方法出现异常时运行的增强功能
-
* 如果方法运行没有出现异常,则该功能不运行
-
* 参数列表可以用Exception ex接收异常对象 需要通过throwing指定异常名称
-
* */
-
@AfterThrowing( value = "addPointCut()",throwing = "ex")
-
public void methodAfterThrowing(Exception ex){
-
System.out.println("AfterThrowing invoked");
-
}
-
/*环绕通知:在切点方法之前和之后都进行功能的增强
-
* 需要在通知中定义方法执行的位置,并在执行位置之前和之后自定义增强的功能
-
* 方法列表可以通过ProceedingJoinPoint获取执行的切点
-
* 通过proceedingJoinPoint.proceed()方法控制切点方法的执行位置
-
* proceedingJoinPoint.proceed()方法会将切点方法的返回值获取到,并交给我们,可以做后续处理
-
* 我们在环绕通知的最后需要将切点方法的返回值继续向上返回,否则切点方法在执行时接收不到返回值
-
* */
-
@Around("addPointCut()")
-
public Object methodAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
-
System.out.println("aroundA invoked");
-
Object proceed = proceedingJoinPoint.proceed();
-
System.out.println("aroundB invoked");
-
return proceed;
-
}
-
}
5、测试代码
-
@Test
-
public void test1(){
-
ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
-
UserDao userDao = context.getBean( UserDao.class);
-
int add = userDao.addUser(10,"晓明");
-
}
6、概念补充
有多个增强类对同一个方法进行增强,通过@Order注解设置增强类优先级
数字越小,优先级越高
数字越小,其代理位置越靠近注入位置
7、完全使用注解开发
创建配置类
-
package com.lanson.config;
-
import org.springframework.context.annotation.ComponentScan;
-
import org.springframework.context.annotation.Configuration;
-
import org.springframework.context.annotation.EnableAspectJAutoProxy;
-
/**
-
* @Author: Lanosnli
-
* @Description: MircoMessage:Mark_7001
-
*/
-
@Configuration
-
@ComponentScan(basePackages = "com.lanson")
-
@EnableAspectJAutoProxy(proxyTargetClass = true)
-
public class SpringConfig {
-
}
测试代码
-
@Test
-
public void test2(){
-
ApplicationContext context=new AnnotationConfigApplicationContext(SpringConfig.class);
-
UserDao userDao = context.getBean( UserDao.class);
-
int add = userDao.addUser(10,"晓明");
-
}
二、XML配置方式实现
1、创建两个类,增强类和被增强类,创建方法
见上面的代码
2、在spring配置文件中创建两个类对象
-
<!--创建对象-->
-
<bean id="userDao" class="com.com.lanson.UserDaoImpl"></bean>
-
<bean id="daoAspect" class="com.com.aspect.DaoAspect"></bean>
3、在spring配置文件中配置切入点
-
<!--配置aop增强-->
-
<aop:config>
-
<!--切入点-->
-
<aop:pointcut id="pointCutAdd" expression="execution(* com.lanson.dao.UserDao.add*(..))"/>
-
<!--配置切面-->
-
<aop:aspect ref="daoAspect">
-
<!--增强作用在具体的方法上-->
-
<aop:before method="methodBefore" pointcut-ref="pointCutAdd"/>
-
<aop:after method="methodAfter" pointcut-ref="pointCutAdd"/>
-
<aop:around method="methodAround" pointcut-ref="pointCutAdd"/>
-
<aop:after-returning method="methodAfterReturning" pointcut-ref="pointCutAdd" returning="res"/>
-
<aop:after-throwing method="methodAfterThrowing" pointcut-ref="pointCutAdd" throwing="ex"/>
-
</aop:aspect>
-
</aop:config>
- 📢博客主页:https://lansonli.blog.csdn.net
- 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!
- 📢本文由 Lansonli 原创,首发于 CSDN博客🙉
- 📢停下休息的时候不要忘了别人还在奔跑,希望大家抓紧时间学习,全力奔赴更美好的生活✨
文章来源: lansonli.blog.csdn.net,作者:Lansonli,版权归原作者所有,如需转载,请联系作者。
原文链接:lansonli.blog.csdn.net/article/details/126810766
【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)