创建切面类和配置文件

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <groupId>com.chentianyu</groupId>
  6. <artifactId>aop_aspectJ_One</artifactId>
  7. <version>1.0-SNAPSHOT</version>
  8. <name>aop_aspectJ_One</name>
  9. <!-- FIXME change it to the project's website -->
  10. <url>http://www.example.com</url>
  11. <properties>
  12. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  13. <maven.compiler.source>1.8</maven.compiler.source>
  14. <maven.compiler.target>1.8</maven.compiler.target>
  15. </properties>
  16. <dependencies>
  17. <!--单元测试-->
  18. <dependency>
  19. <groupId>junit</groupId>
  20. <artifactId>junit</artifactId>
  21. <version>4.11</version>
  22. <scope>test</scope>
  23. </dependency>
  24. <!--spring依赖-->
  25. <dependency>
  26. <groupId>org.springframework</groupId>
  27. <artifactId>spring-context</artifactId>
  28. <version>5.3.16</version>
  29. </dependency>
  30. <!--aspectj依赖-->
  31. <dependency>
  32. <groupId>org.springframework</groupId>
  33. <artifactId>spring-aspects</artifactId>
  34. <version>5.3.17</version>
  35. </dependency>
  36. </dependencies>
  37. <build>
  38. </build>
  39. </project>

da01.SomeService.java

package com.chentianyu.ba01;

public interface SomeService {
    void doSome(String name,Integer age);
}

实现接口: SomeServiceImpl.java

package com.chentianyu.ba01;

public class SomeServiceImpl implements SomeService {
    @Override
    public void doSome(String name,Integer age) {
        //给doSome方法增加一个功能,在doSome()执行之前,输出方法的执行时间
        System.out.println("====目标方法执行doSome()====");
    }
}

创建切面类

package com.chentianyu.ba01;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

import java.util.Date;

/**
 * @Aspect : 是aspectj框架中的注解。
 *  作用: 表示当前类是切面类。
 *  切面类是用来给业务方法增加功能的类,在这个类中有切面的功能代码
 *  位置: 定义在类上面
 */
@Aspect
public class MyAspect {
    /**
     * 定义方法,方法是实现切面功能的。
     * 方法的定义要求:
     *  1.公共方法 public
     *  2.方法没有返回值
     *  3.方法名称自定义
     *  4.方法可以有参数。也可以没有参数;如果有参数,这个参数不是自定义的,有几个参数类型可以使用
     *  
     * @Before: 前置通知注解
     *  属性: value: 是切入点表达式,表示切面的功能执行的位置
     *  位置: 在方法上面
     *  特点: 
     *      1.在目标方法之前执行的
     *      2.不会改变目标方法的执行结果
     *      3.不会影响你目标方法的执行
     */@Before(value = "execution(public void com.chentianyu.ba01.SomeServiceImpl.doSome(String,Integer))")
    public void myBefore(){
        //这里就是你切面要执行的功能代码
        System.out.println("前置通知,切面功能: 在目标方法之前输出执行时间:" + new Date());
    }
}
<?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 
       https://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--把对象交给spring容器,由spring统一创建,管理对象-->
    <!--声明目标对象-->
    <bean id="someService" class="com.chentianyu.ba01.SomeServiceImpl" />

    <!--声明切面对象-->
    <bean id="myAspect" class="com.chentianyu.ba01.MyAspect" />

    <!--声明自动代理生成器: 使用aspectj框架的内部的功能,创建目标对象的代理对象。
    创建代理对象是在内存中实现的,修改目标对象的内存中的结构。创建为代理对象
    所以你的目标对象就是一个被修改的代理对象

    aspectj-autoproxy:会把spring容器中所有的目标对象一次性都生成代理对象
-->
    <aop:aspectj-autoproxy />
</beans>

找到@Before(value = "execution(public void com.chentianyu.ba01.SomeServiceImpl.doSome(String,Integer))")找到目标(SomeServiceImpl)生成代理

测试:

public class testApp01 {
    @Test
    public void test01(){
        String config = "applicationContext.xml";
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext(config);
        //从容器中获取目标对象
        SomeService proxy = (SomeService) applicationContext.getBean("someService");
        //通过代理的对象执行方法,实现目标方法执行时,增强了功能
        proxy.doSome("李四",20);
    }
}
前置通知,切面功能: 在目标方法之前输出执行时间:Fri Apr 08 16:12:17 CST 2022
====目标方法执行doSome()====

先执行了切面的功能