目录
2.创建目标接口,定义抽象方法,并实现目标接口的实现类,重写方法(目标方法)
前言
使用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修改目标方法的返回值,那么该环绕通知的方法需要有返回值










