一、引入maven库如下:?
- AOP(Aspect Oriented Programming),面向切面编程
- Spring使用AOP技术封装了动态代理的功能,使用起来非常简单
- 它依赖于AspectJ库如下:
<!--Spring AOP-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.6</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
二、创建aop相关类如下:
1、在业务方法之前调用,无法配置:
package com.mj.aop;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
public class LogAdvice implements MethodBeforeAdvice {
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println("LogAdvice---before--------");
}
}
2、可以进行手动配置如下:
package com.mj.aop;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class LogInterceptor implements MethodInterceptor {
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
System.out.println("LogInterceptor ----- 1");
/*调用目标对象的目标方法*/
Object result = methodInvocation.proceed();
System.out.println("LogInterceptor ----- 2");
return result;
}
}
?三、配置文件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: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">
<bean id="userService" class="com.mj.service.impl.UserServiceImpl"/>
<bean id="personService" class="com.mj.service.impl.PersonServiceImpl"/>
<bean id="skillService" class="com.mj.service.SkillService"/>
<!--附加代码-->
<!-- <bean id="logAdvice" class="com.mj.aop.LogAdvice"/>-->
<bean id="interceptor" class="com.mj.aop.LogInterceptor"/>
<!--aop切面-->
<!--true代表强制使用CGLib;false代表使用默认方案-->
<aop:config proxy-target-class="true">
<!--切入点:给哪些类的哪些方法增加附加代码-->
<!--execution(* *(..)) 代表所有类的所有方法都会被切入-->
<aop:pointcut id="pc" expression="execution(* *(..))"/>
<!--附加代码-->
<aop:advisor advice-ref="interceptor" pointcut-ref="pc"/>
</aop:config>
</beans>
切入点表达式:
- 任意公共方法:execution(public * *(..))?
- 名字以set开头的任意方法:execution(* set*(..))
- UserService接口定义的任意方法:execution(* com.mj.service.UserService.*(..))
- service包中定义的任意方法:execution(* com.mj.service.*.*(..))
- service包中定义的任意方法(包括子包):execution(* com.mj.service..*.*(..))
- 包含2个String参赛的任意方法:execution(* *(String, String))
- 带有自定义注解(Hehe)的方法:@annotation(com.mj.aop.Hehe)
能配置多个pointcut、advisor如下图:

?
四、测试类
public class UserTest {
@Test
public void test(){
// 创建容器
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService service = ctx.getBean("userService", UserService.class);
service.login("小马哥","123456");
PersonService personService = ctx.getBean("personService",PersonService.class);
personService.run();
SkillService service1 = ctx.getBean("skillService", SkillService.class);
service1.save(null);
// 关闭容器
ctx.close();
}
}
五、AOP动态代理的底层实现
- 如果目标类有实现接口,使用JDK实现
- 如果目标类没有实现接口,使用CGLib实现
- 可以通过proxy-target-class属性修改底层实现方案:true代表强制使用CGLib;false代表使用默认方案
|