目录
本章学习源码Github地址:https://github.com/GuiZhouAndroid/MySpringAllProject/tree/master/SpringDemo09_AspectJ/src/main/java/com/dhrj/java/zsitking/before
一、AspectJ开发环境
(1)pom依赖
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<!-- Spring依赖配置 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.20</version>
</dependency>
<!-- AspectJ依赖配置 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.3.20</version>
</dependency>
</dependencies>
<build>
<resources>
<!-- 扫描加载java目录下指定后缀资源 -->
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
</includes>
</resource>
<!-- 扫描加载resources目录下指定后缀资源 -->
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
</includes>
</resource>
</resources>
</build>
(2)Spring配置文件
<?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: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/context https://www.springframework.org/schema/context/spring-context.xsd">
</beans>
实现步骤:
(1)创建业务接口
(2)创建业务实现
(3)创建切面类,实现切面方法
(4)在Spring的applicationContext.xml配置文件中进行切面绑定——>IOC+AspectJ内置代理模式(默认JDK动态代理+CGLib子类代理)
二、前置通知切面开发
在目标方法执行前切入切面功能,在切面方法中不可以获得目标方法的返回值,只能得到目标方法的签名和参数(JoinPoint)——>修饰符类型+返回值类型+方法名+形式参数
(1)前置通知业务接口
//前置通知业务接口
public interface BeforeService {
//前置通知方法
void beforeMethod();
//我的信息
String myInfo(String name, int age);
}
(2)前置通知业务接口实现类
//前置通知业务接口实现
@Service //Spring的IOC注解式创建业务逻辑层实例
public class BeforeServiceImpl implements BeforeService {
@Override
public void beforeMethod() {
System.out.println("前置通知业务接口实现");
}
@Override
public String myInfo(String name, int age) {
return "我的个人信息 = 姓名:" + name + ",年龄:" + age;
}
}
(3)前置通知切面类
前置通知中创建切面方法的规范:
(1)访问修饰符权限是public
(2)方法的返回值是void
(3)方法名称是自定义
(4)可以没有方法形式参数,如果有,必为JoinPoint类型
(5)必须使用@Before注解来声明切入的时机是前切功能和切入点
//前置通知使用AspectJ实现AOP功能,此类为切面类,包含各种切面方法
@Aspect //交给AspectJ的框架去识别切面类
@Component //切面实例注册加载到spring容器中
public class BeforeAspectJ {
/**
* 各种切面都在此类中进行开发
* (1)访问修饰符权限是public
* (2)方法的返回值是void
* (3)方法名称是自定义
* (4)可以没有方法形式参数,如果有,必为JoinPoint类型
* (5)必须使用@Before注解来声明切入的时机是前切功能和切入点
*/
/**
* ...before.impl包下BeforeServiceImpl类中返回值是void类型并且公开的任意形参的任意方法都织入以下AOP功能
*/
@Before(value = "execution(public void com.dhrj.java.zsitking.before.impl.BeforeServiceImpl.*(..))")//切入点表达式,此处为前置通知
public void myBeforeMethod() {
System.out.println("我是切面类中的AOP,前置通知呀~");
}
/**
* ...before.impl包下任意类中返回值是String类型并且形参顺序为(String,int)公开的任意方法都织入以下AOP功能
*/
@Before(value = "execution(public String com.dhrj.java.zsitking.before.impl.*.*(String,int))")//切入点表达式,此处为前置通知
public void myInfoBefore() {
System.out.println("我是切面类中的AOP,个人信息呀~");
}
/**
* ...before.impl包下任意类中任意返回值类型并且公开的任意形参的任意方法都织入以下AOP功能
*/
@Before(value = "execution(public * com.dhrj.java.zsitking.before.impl.*.*(..))")//切入点表达式,此处为前置通知
public void myBeforeAll01() {
System.out.println("我是切面类中的AOP,....before.impl包下任意公开类中任意方法的任意参数呀~");
}
/**
* ...before本包及其子包中任意类下任意返回值类型并且任意形参的任意方法都织入以下AOP功能
*/
@Before(value = "execution( * com.dhrj.java.zsitking.before..*.*(..))")//切入点表达式,此处为前置通知
public void myBeforeAll02() {
System.out.println("我是切面类中的AOP,....before包下以及多个子包下全部类中的方法呀~");
}
/**
* 项目工程路径下全部中和方法都能都织入以下AOP功能——>不推荐使用,扫描效率极低,影响程序执行性能
*/
@Before(value = "execution( * *(..))")//切入点表达式,此处为前置通知
public void myBeforeAll03() {
System.out.println("我是切面类中的AOP,....项目工程路径下全部中和方法呀~");
}
/**
* ...before本包任意类下任意返回值类型并且任意形参的任意方法都织入以下AOP功能——>获取目标方法的签名和参数
*/
@Before(value = "execution( * com.dhrj.java.zsitking.before.*.*(..))")
public void myBeforeJoinPointArgs(JoinPoint jp) {
System.out.println("目标方法的签名:" + jp.getSignature());
System.out.println("目标方法的参数:" + Arrays.toString(jp.getArgs()));
}
}
(4)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: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/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--基于注解的访问要添加包扫描-->
<context:component-scan base-package="com.dhrj.java.zsitking.before"/>
<!--业务实现绑定AOP,默认是JDK动态代理,取时必须使用接口类型-->
<aop:aspectj-autoproxy/>
<!-- <aop:aspectj-autoproxy proxy-target-class="true"/>设置为CGLib子类代理,可以使用接口和实现类接-->
</beans>
三、junitl测试
//前置通知测试类
public class BeforeTest {
private BeforeService beforeService;
@Before //junit
public void before() {
ApplicationContext ac = new ClassPathXmlApplicationContext("before/applicationContext.xml");
beforeService = (BeforeService) ac.getBean("beforeServiceImpl");
System.out.println("绑定切面后的对象类型:" + beforeService.getClass());
}
@Test
public void testBefore01() {
beforeService.beforeMethod();
}
@Test
public void testBefore02() {
System.out.println(beforeService.myInfo("张松", 24));
}
}
(1)运行testBefore01
(2)运行testBefore02
四、总结
仅自己学习记录,如有错误,敬请谅解~,谢谢~~~