其他分享
首页 > 其他分享> > 关于Spring的学习总结(三)

关于Spring的学习总结(三)

作者:互联网

文章目录


一、理解AOP

AOP(Aspect Oriented Programming),面向切面思想,是Spring的三大核心思想之一(两外两个:IOC-控制反转、DI-依赖注入)。

(一)什么是AOP

用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

下面有一些图片辅助理解:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(二)AOP中的相关概念

二、使用Spring实现AOP

导入依赖

<dependency>
		<groupId>org.aspectj</groupId>
  	<artifactId>aspectjweaver</artifactId>
  	<version>1.9.4</version>
</dependency>

使用Aspectj实现AOP有俩种方式:基于XML的声明式基于注解的声明式

(一)基于XML的声明式

基于XML的声明式是指通过XML文件来定义切面、切入点以及通知,所有切面、切入点和通知都必须定义在<aop:config>元素中。

Spring配置文件中的<bean>元素下可以包含多个<aop:config>元素,一个<aop:config>元素中有可以包含属性和子元素,子元素包括<aop:pointcut><aop:advisor><aop:aspect>,配置的时候也必须按照此顺序来。

常用配置代码如下:

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

       <!--定义切面Bean-->
       <bean id="myAspect" class="com.weirdo.aspectj"/>
       <aop:config>
              <!--1.配置切面-->
              <aop:aspect id="aspect" ref="myAspect">
                     <!--2.配置切入点-->
                     <aop:pointcut id="myPointCut" expression="execution(* com.weirdo.aspectj.* (..))"/>
              <!--3.配置通知-->
                     <!--前置通知-->
                     <aop:before method="myBefore" pointcut-ref="myPointCut"/>
                     <!--后置通知-->
                     <aop:after-returning method="myAfterReturning" pointcut-ref="myPointCut" returning="returnVal"/>
                     <!--环绕通知-->
                     <aop:around method="myAround" pointcut-ref="myPointCut"/>
                     <!--异常通知-->
                     <aop:after-throwing method="myAfterThrowing" pointcut-ref="myPointCut" throwing="e"/>
                     <!--最终通知-->
                     <aop:after method="myAfter" pointcut-ref="myPointCut"/>
              </aop:aspect>
       </aop:config>
</beans>
  1. UserDao.java
public interface UserDao {
    public void addUser();
    public void deleteUser();
}
  1. UserDaoImpl.java
public class UserDaoImpl implements UserDao{

    @Override
    public void addUser() {
        System.out.println("添加新用户");
    }

    @Override
    public void deleteUser() {
        System.out.println("删除用户");
    }
}
  1. MyAspectj.java
/**
 * 切面类,此面写通知
 */
public class MyAspectj {
    //前置通知
    public void myBefore(JoinPoint joinPoint){
        System.out.println("前置通知:模拟执行权限检查");
        System.out.println("目标类"+joinPoint.getTarget());
        System.out.println("被植入的强处理的目标方法为"+joinPoint.getSignature().getName());
    }
    //后置通知
    public void myAfterReturning(JoinPoint joinPoint){
        System.out.println("后置通知:模拟记录日志");
        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("最终通知:模拟方法结束后释放资源");
    }
}
  1. 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">

    <!--目标类-->
    <bean id="userDao" class="com.weirdo.dao.UserDaoImpl"/>
    <!--切面-->
    <bean id="myAspectj" class="com.weirdo.dao.MyAspectj"/>
    <aop:config>
        <!--1.配置切面-->
        <aop:aspect id="aspect" ref="myAspectj">
            <!--2.配置切入点-->
            <aop:pointcut id="myPointCut" expression="execution(* com.weirdo.dao.MyAspectj.*.*(..))"/>
            <!--3.配置通知-->
            <!--前置通知-->
            <aop:before method="myBefore" pointcut-ref="myPointCut"/>
            <!--后置通知-->
            <aop:after-returning method="myAfterReturning" pointcut-ref="myPointCut" returning="joinPoint"/>
            <!--环绕通知-->
            <aop:around method="myAround" pointcut-ref="myPointCut"/>
            <!--异常通知-->
            <aop:after-throwing method="myAfterThrowing" pointcut-ref="myPointCut" throwing="e"/>
            <!--最终通知-->
            <aop:after method="myAfter" pointcut-ref="myPointCut" />
        </aop:aspect>
    </aop:config>
</beans>
  1. TestXMLAspectj.java
public class TestXMLAspectj {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao userDao = (UserDao) context.getBean("userDao");
        userDao.deleteUser();
    }
}

(二)基于注解的声明式

  1. 在UserDaoImpl类上添加@Repository("userDao")
  2. MyAspect.java
/**
 * 切面类,此面写通知
 */
@Aspect
@Component
public class MyAspectj {
    //定义切入点表达式
    @Pointcut("execution(* com.weirdo.dao.MyAspectj.*.*(..))")
    //使用一个返回值为void 方法体为空的方法来命名切入点
    public 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 myAfterReturning(JoinPoint joinPoint){
        System.out.println("后置通知:模拟记录日志");
        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("最终通知:模拟方法结束后释放资源");
    }
}

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

       <!--指定需要扫描的包,使用注解生效-->
       <context:component-scan base-package="com.weirdo"/>
       <!--启动基于注解的声明式支持-->
       <aop:aspectj-autoproxy />
</beans>

标签:总结,Spring,void,joinPoint,System,学习,println,public,out
来源: https://blog.csdn.net/weixin_46647863/article/details/121440754