Spring基础:AOP注解和XML方式实现

Posted Lansonli

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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博客🙉
  • 📢停下休息的时候不要忘了别人还在奔跑,希望大家抓紧时间学习,全力奔赴更美好的生活✨

以上是关于Spring基础:AOP注解和XML方式实现的主要内容,如果未能解决你的问题,请参考以下文章

Spring Aop实现方式(注解和Xml)

这些简单的Spring Bean注入方式,你都会吗?

一起学Spring之注解和Schema方式实现AOP

Spring详解------AOP 注解

Spring系列之AOP实现的两种方式

Spring笔记--注解方式实现AOP