欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

AOP基于纯注解开发

程序员文章站 2022-03-01 12:57:26
...

目录

前言

一、纯注解开发

二、操作步骤

1.导入依赖

2.创建目标接口,定义抽象方法,并实现目标接口的实现类,重写方法(目标方法)

3.创建通知类,定义通知方法

4.创建Spring核心配置类

5.测试类

6.测试结果

三、注解解释:

四、注意事项:


前言

  使用xml配置AOP的方法,稍微有些许麻烦,在企业开发中,绝大部分使用注解开发的,效率杠杠的。如果需要了解基于xml方式配置AOP,去找的上一篇文章!


提示:以下是本篇文章正文内容,下面案例可供参考

一、纯注解开发

  •  其实注解开发就是剔除掉Spring的配置文件,使用注解的方式去替代在配置文件所做的事情
  • 在xml配置文件,我们需要把通知类、目标类使用<bean>标签创建出来,然后交给Spring的IOC容器管理。然后在配置AOP

二、操作步骤

1.导入依赖

代码如下(示例):

<dependencies>
        <!--Spring上下文核心包-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.1.2.RELEASE</version>
        </dependency>
        <!--AOP的实现包-->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.4</version>
        </dependency>
        <!--Spring和单元测试集成-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.1.2.RELEASE</version>
        </dependency>
        <!--单元测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
 </dependencies>

2.创建目标接口,定义抽象方法,并实现目标接口的实现类,重写方法(目标方法)

代码如下(示例):

/**
 * @Author:Yan
 * @Date 2022/01/21 20:07
 * @Description 目标接口
 **/
public interface Target {
    String getName(String name);
}
/**
 * @Author:Yan
 * @Date 2022/01/21 20:08
 * @Description 目标接口的实现类
 **/
//@Component注解,相当于使用了<bean>,表示创建类的对象并交给IOC容器管理
@Component
public class TargetImpl implements Target {
    @Override
    public String getName(String name) {
        System.out.println("目标方法...."+name);
        return name;
    }
}

3.创建通知类,定义通知方法

代码如下(示例):

/**
 * @Author:Yan
 * @Date 2022/01/21 19:56
 * @Description 3、创建通知类,定义通知方法
 *    1、通知类使用@Aspect表示该类为切面类 并使用@Component注解表示创建该类对象交给Spring管理
 *    2、定义一个方法,使用@Pointcut("切入点表达式")注解  该方法毫无意义
 *    3、方法使用@通知类型("切入点表达式的方法ming()")
 **/
@Aspect     //表示该方类为切面类
@Component
public class MyAdvice {
    //2、定义一个方法,使用@Pointcut("切入点表达式")注解
    @Pointcut("execution(* com.itheima..*.*(..))")
    public void pointcut() {
    }

    //3、方法使用@通知类型
    @Before("pointcut()")
    public void before() {
        System.out.println("前置通知-->打印日志");
    }

    @After("pointcut()")
    public void after() {
        System.out.println("最终通知-->打印日志");
    }

    @AfterReturning("pointcut()")
    public void afterRun() {
        System.out.println("返回后通知-->打印日志");
    }

    @AfterThrowing("pointcut()")
    public void afterThrow() {
        System.out.println("抛出异常后通知-->打印日志");
    }

    @Around("pointcut()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        //获取目标方法的参数
        pjp.getArgs()[0] = "李四";
        System.out.println("环绕通知-->打印日志");
        //将设置好的目标方法参数传回去
        Object proceed = pjp.proceed(pjp.getArgs());
        //并返回,如果不返回,那么接收到的返回值为null
        return proceed;
    }
}

4.创建Spring核心配置类

/**
 * @Author:Yan
 * @Date 2022/01/21 20:09
 * @Description 核心配置类
 *  1、使用@Configuration  表示为该类为核配置类
 *  2、使用@ComponentScan("包的路径")  表示为开启注解扫描
 *  3、使用@EnableAspectJAutoProxy  表示开启AOP注解扫描
 **/
@Configuration  //表示该类为Spring核心配置类
@ComponentScan("com.itheima")  //开启注解扫描
@EnableAspectJAutoProxy  //表示开启AOP注解驱动
public class AppConfig {
}

5.测试类

/**
 * @Author:Yan
 * @Date 2022/01/21 20:14
 * @Description 测试纯注解
 **/
@RunWith(SpringJUnit4ClassRunner.class)    //表示该类测试类
@ContextConfiguration(classes = AppConfig.class)
public class textAnno {
    //定义目标类的属性  使用@Autowiredr注解为该属性注入数据
    @Autowired
    private Target target;

    @Test
    public void method() {
        //调用方法
        String name = target.getName("张三");
        System.out.println(name);
    }
}

6.测试结果

环绕通知-->打印日志
前置通知-->打印日志
目标方法....李四
最终通知-->打印日志
返回后通知-->打印日志
李四

三、注解解释:

  •  @Aspect:该注解作用在类上,表示该类是一个切面类。替代xml方式中的<aop:aspect ref="通知类唯一标识">
  •  @Component:该注解作用在类上,用于创建该类的对象并交给IOC容器管理,替代xml方式中的<bean>标签

  • @Pointcut("execution= "):该注解作用于方法上,使用当前方法名作为切入点引用名称,方法毫无意义。execution属性用于定义切入点表达式。替代xml方式中的<aop:pointcut id="" expression="execution(切入点表达式)"/>

  • @Before("切入点方法名()") 、@After("切入点方法名()")、@AfterReturning("切入点方法名()")、@AfterThrowing("切入点方法名()")、@Around("切入点方法名()"):这些注解作用于方法上,表示该方法属于何种通知类型,并指定切入点表达式。

  • @Configuration  该注解作用于类上,表示该类为Spring核心配置类   一般用于配置类上

  • @ComponentScan("com.itheima")  该注解作用于类上,表示开启Spring注解扫描。  一般用于配置类上

  • @EnableAspectJAutoProxy  该注解作用于类上,表示开启AOP注解驱动。一般用于配置类上

  • @RunWith(SpringJUnit4ClassRunner.class)   该注解作用于类上,表示该类测试类。

  • @ContextConfiguration(classes = AppConfig.class)  该注解作用于类上,用于读取Spring配置文件。替代了xml方式需要创建工厂对象

四、注意事项:

  • 如果一个类中的方法被使用AOP增强了  则在SpringIOC容器中管理的是这个类的代理对象  代理对象类型不是实现类类型 但是属于接口类型所以 在使用 AOP之后 获取一个bean对象 通过接口类型获取  不能在通过实现类类型获取了只要类中有一个方法被AOP增强了 则存在Spring IOC容器中的bean对象 就是代理对象 必须使用接口类型获取接收

  • 定义环绕增强时 就需要设置方法参数了,如果不设置 其功能就等价于前置增强  ProceedingJoinPoint就是要进行增强的目标方法

                      不是设置参数时,会执行环绕通知,而不会执行前置通知

                      使用 ProceedingJoinPoint获取方法参数 重新赋值  修改参数  需要将该参数传递给目标方法

                       proceed():调用目标方法执行  如果有参数就在小括号中传递

                      环绕通知可以使用 ProceedingJoinPoint修改目标方法的返回值,那么该环绕通知的方法需要有返回值

相关标签: Spring框架 后端