🧸安清h:个人主页
🎥个人专栏:【计算机网络】【Mybatis篇】【Spring篇】
🚦作者简介:一个有趣爱睡觉的intp,期待和更多人分享自己所学知识的真诚大学生。
目录
🎯初始Sprig AOP及术语
🎯基于XML的AOP实现
🚦配置Spring AOP的XML元素
✨配置切面
✨配置切入点
🚦示例
✨创建UserDao类
✨创建UserDaoImpl类
✨创建XmlAdvice类
✨applicationContext-xml.xml文件
✨创建测试类
🎯基于注解的AOP实现
🚦Spring提供的注解
🚦代码示例
✨创建UserDao类
✨创建UserDaoImpl类
✨创建AnnoAdvice类
✨applicationConext.xml文件
✨创建测试类
🎯初始Sprig AOP及术语
Spring AOP(Aspect-Oriented Programming,面向切面编程)是Spring框架中的一个核心模块,它允许开发者将横切关注点(如日志、事务管理、安全等)从业务逻辑中分离出来,以提高代码的模块化和可重用性。以下是一些Spring AOP中常用的术语,根据例子来展示其用法:
LogUtils中的printLog()方法用来输出日志
需求:针对UserService的save和delete方法做日志输出的增强
Join Point(连接点):能够被增强的叫做连接点。特指的是类中的方法,以上四个任何一个方法都可以被叫做连接点
Pointcut(切入点):将要被增强的方法。一个切入点一定是一个连接点,但是一个连接点并不一定是一个切入点。在例子中save()和delete()为切入点。
Advice(增强/通知):将要增强的功能所在的方法。例子中由于要对save和delete方法做日志的增强,所以printLog方法叫做增强advice。
Aspect(切面):用来配置切入点和增强关系的。
Target (目标对象):指的是将要被增强的方法所在的对象。例子中UserService对象就是Target对象。
Weaving(织入):将增强运用到切入点的过程叫做织入。
Proxy(代理):将增强运用到切入点之后形成的对象叫做代理对象。
🎯基于XML的AOP实现
Spring中AOP的代理对象是由IOC容器自动生成,所以开发者只需选择选择连接点,创建切面,定义切点并在XML中添加配置信息即可。Spring提供了一系列配置Spring AOP的XML元素。
AOP配置:在切面中配置切入点和增强的关系
🚦配置Spring AOP的XML元素
元素 | 描述 |
---|---|
<aop:config> | Spring AOP配置的根元素 |
<aop:aspect> | 配置切面 |
<aop:pointcut> | 配置切入点 |
<aop:before> | 定义一个前置通知 |
<aop:after> | 定义一个后置通知 |
<aop:after-returning> | 定义一个返回后通知 |
<aop:around> | 定义一个环绕通知 |
✨配置切面
在定义<aop:aspect>元素时,通常会指定id,ref这两个属性。
属性名称 | 描述 |
---|---|
id | 用于定义切面的唯一标识,切面起的名字(可以不设置) |
ref | 用于引用普通的Spring Bean,引用的切面类对象bean的id值 |
✨配置切入点
在定义<aop:pointcut>元素时,通常会指定id,expression这两个属性。
属性名称 | 描述 |
---|---|
id | 用于指定切入点的唯一标识 |
expression | 用于指定切入点关联的切入点的表达式 |
🚦示例
✨创建UserDao类
定义了用户数据操作的接口,包括增删改查四个方法。
public interface UserDao {
public void insert();
public void delete();
public void update();
public void select();
}
✨创建UserDaoImpl类
实现了UserDao接口,具体执行数据库操作的打印语句。
public class UserDaoImpl implements UserDao{
@Override
public void insert() {
System.out.println("添加用户信息");
}
@Override
public void delete() {
System.out.println("删除用户信息");
}
@Override
public void update() {
System.out.println("修改用户信息");
}
@Override
public void select() {
System.out.println("查询用户信息");
}
}
✨创建XmlAdvice类
定义了AOP切面,包含前置、后置、环绕、返回和异常通知方法。
public class XmlAdvice {
// 前置通知
public void before(JoinPoint joinPoint) {
System.out.println("这是前置方法");
System.out.println("目标类是:" + joinPoint.getTarget());
System.out.println(",被织入增强处理的目标方法为:" + joinPoint.getSignature().getName());
}
// 返回通知
public void afterReturning(JoinPoint joinPoint) {
System.out.println("这是返回通知,方法不出现异常时调用");
System.out.println(",被织入增强处理的目标方法为:" + joinPoint.getSignature().getName());
}
// 环绕通知
public Object around(ProceedingJoinPoint point) throws Throwable {
System.out.println("这是环绕之前的通知");
Object object = point.proceed();
System.out.println("这是环绕之后的通知");
return object;
}
// 异常通知
public void afterException() {
System.out.println("异常通知!");
}
// 后置通知
public void after() {
System.out.println("这是后置通知!");
}
}
✨applicationContext-xml.xml文件
Spring配置文件,配置了数据源、事务管理器、UserDaoImpl和XmlAdvice的Bean,并定义了AOP的切点和通知。
<?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"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<aop:aspectj-autoproxy/>
<context:component-scan base-package="com.xml"/>
<bean id="userDao" class="com.xml.UserDaoImpl"/>
<bean id="xmlAdvice" class="com.xml.XmlAdvice"/>
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* com.xml.UserDaoImpl.*(..))"/>
<aop:aspect ref="xmlAdvice">
<aop:before method="before" pointcut-ref="pointcut"/>
<aop:after-returning method="afterReturning" pointcut-ref="pointcut"/>
<aop:around method="around" pointcut-ref="pointcut"/>
<aop:after-throwing method="afterException" pointcut-ref="pointcut"/>
<aop:after method="after" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>
</beans>
✨创建测试类
测试类,通过Spring容器获取UserDao的Bean,并调用其方法来验证AOP功能是否正常工作。
public class TestXml {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext-xml.xml");
UserDao userDao = applicationContext.getBean("userDao", UserDao.class);
userDao.delete();
System.out.println();
userDao.insert();
System.out.println();
userDao.select();
System.out.println();
userDao.update();
}
}
这是部分运行出来的结果,由于过长,所以在这里只截取了delete部分的作为参考:
🎯基于注解的AOP实现
🚦Spring提供的注解
注解名称 | 描述 |
---|---|
@Aspect | 配置切面 |
@Pointcut | 配置切入点 |
@Before | 配置前置通知 |
@After | 配置后置通知 |
@Around | 配置环绕通知 |
@AfterReturning | 配置返回通知 |
@AfterThrowing | 配置异常通知 |
下面将通过一个示例来展现:
🚦代码示例
✨创建UserDao类
声明用户数据操作的接口
public interface UserDao {
public void insert();
public void delete();
public void update();
public void select();
}
✨创建UserDaoImpl类
实现UserDao接口,标注为Spring管理的Bean,并定义基本的数据库操作打印语句。
@Component("userDao")
public class UserDaoImpl implements UserDao{
@Override
public void insert() {
System.out.println("添加用户信息");
}
@Override
public void delete() {
System.out.println("删除用户信息");
}
@Override
public void update() {
System.out.println("修改用户信息");
}
@Override
public void select() {
System.out.println("查询用户信息");
}
}
✨创建AnnoAdvice类
定义切面,包括前置、后置、环绕、返回和异常通知,用于增强UserDaoImpl类的方法
@Aspect //告诉Spring,这个东西是用来做AOP的
public class AnnoAdvice {
//切点
@Pointcut("execution(* com.xml.UserDaoImpl.*(..))")
public void pointcut(){}
//前置通知
@Before("pointcut()") //切入点和通知的绑定
public void before(JoinPoint joinPoint){
System.out.println("这是前置通知");
System.out.println("目标类是:"+joinPoint.getTarget());
System.out.println(",被织入增强处理的目标方法为:"+joinPoint.getSignature().getName());
}
//返回通知
@AfterReturning("pointcut()")
public void afterReturning(JoinPoint joinPoint){
System.out.println("这是返回通知");
System.out.println(",被织入增强处理的目标方法为:"+joinPoint.getSignature().getName());
}
//环绕通知
@Around("pointcut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
System.out.println("这是环绕通知之前的部分");
Object object=point.proceed();
System.out.println("这是环绕通知之后的部分");
return object;
}
//异常通知
@AfterThrowing("pointcut()")
public void afterException(){
System.out.println("这是异常通知");
}
//后置通知
@After("pointcut()")
public void after(){
System.out.println("这是后置通知");
}
}
✨applicationConext.xml文件
配置Spring的AOP命名空间、组件扫描和切面相关的Bean定义
<?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"
xmlns:context="http://www.springframework.org/schema/context"
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 http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<aop:aspectj-autoproxy/>
<context:component-scan base-package="com.xml"/>
<bean id="annoAdvice" class="com.xml.AnnoAdvice"/>
</beans>
✨创建测试类
通过Spring容器获取UserDao的Bean,并调用其方法,预期将触发AnnoAdvice中定义的AOP通知
public class TestAnnotation {
public static void main(String[]args){
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao=applicationContext.getBean("userDao", UserDao.class);
userDao.delete();
System.out.println();
userDao.insert();
System.out.println();
userDao.select();
System.out.println();
userDao.update();
}
}
以上就是今天要讲的内容了,主要讲解了Spring AOP的术语及其两种实现方式等相关内容,如果您感兴趣的话,可以订阅我的相关专栏。非常感谢您的阅读,如果这篇文章对您有帮助,那将是我的荣幸。我们下期再见啦🧸!