Spring的基础和应用系列文章目录
第一部分 Spring 基础
1.1 XML使用-IoC配置与依赖(DI)配置
1.2 基于注解和XML混合方式的使用
1.3 基于纯注解方式的使用
1.4 AOP 介绍
1.5 Spring 整合AspectJ的AOP使用
第二部分 组件支持
2.1 Spring 整合Junit
2.2 Spring 事务支持
Spring 整合AspectJ的AOP使用
是指的Spring + AspectJ整合,不过Spring已经将AspectJ收录到自身的框架中了,并且底层织入依然是采取的动态织入方式。
前置条件
1、 导入依赖
<!-- 基于AspectJ的aop依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.0.7.RELEASE</version>
</dependency>
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
2 编写目标类和目标方法
2.1 编写接口和实现类(目标对象)
UserService接口
UserServiceImpl实现类
2.2 配置目标类,将目标类交给spring IoC容器管理
<context:component-scan base-package="sourcecode.ioc" />
一、使用XML实现
1.1 实现步骤
1 编写通知(增强类,一个普通的类)
public class MyAdvice {
public MyAdvice() {
}
public void after() {
System.out.println("最终通知...");
}
}
2 配置通知,将通知类交给spring IoC容器管理
将第一步编写的通知类交给Spring 管理。
<!-- 配置通知类 -->
<bean id="myAdvice" class="com.kkb.spring.aop.advice.MyAdvice"></bean>
3 配置AOP 切面
切入点和通知是切面。method 是 ref 对应类的增强方法。
使用:
<aop:config>
<aop:aspect ref="myAdvice">
<!-- method属性:对应myAdvice类的after方法, 要增强的方法名 -->
<!-- pointcut属性:指定切入点类AspectJExpressionPointcut, 需要配置切入点表达式 -->
<aop:after method="after"
pointcut="execution(* *..*.*ServiceImpl.*(..))" />
</aop:aspect>
</aop:config>
详细说明:
<aop:before method="before"
pointcut="execution(* *..*.*ServiceImpl.*(..))" />
<!-- 对应 AspectJAfterAdvice 通知类 -->
<!-- AspectJAfterAdvice构造参数: -->
<!-- 第一个构造参数:method属性指定的方法的Method对象 -->
<!-- 第二个构造参数:pointcut属性对应的切入点对象 -->
<!-- 第三个构造参数:产生myAdvice类的工厂对象 -->
<!-- 第二个参数的作用:确定哪些类运行时,调用AspectJAfterAdvice的after方法 -->
<!-- 第一个参数和第三个参数的作用:一旦调用after方法的时候,就会调用method.invoke(obj,args) -->
Spring AOP实现的配置(了解)
<!-- 这是使用的Spring AOP实现 -->
<aop:advisor advice-ref="" pointcut=""/>
1.2 切入点表达式
1.2.1 表达式格式:
execution([修饰符] 返回值类型 包名.类名.方法名(参数))
1.2.2 表达式格式说明
1、 execution:必须要
2、修饰符:可省略
3、返回值类型:必须要,但是可以使用*通配符
4、包名 :
- 多级包之间使用
.
分割 - 包名可以使用代替,多级包名可以使用多个
*
代替 、 - 如果想省略中间的包名可以使用
..
5、 类名、方法名:
可以使用*
6、 参数:
如果有多个参数,可以使用 ..
代替
示例:
"execution(void cn.spring.dao.UserDaoIml.insert())" />
1.3 通知类型
通知类型(五种):前置通知、后置通知、最终通知、环绕通知、异常抛出通知。
1.3.1 前置通知
- 执行时机:目标对象方法之前执行通知
- 配置文件:<aop:before method=“before” pointcut-ref=“myPointcut”/>
- 应用场景:方法开始时可以进行校验
1.3.2 后置通知
- 执行时机:目标对象方法之后执行通知,有异常则不执行了 *
- 配置文件:<aop:after-returning method=“afterReturning” pointcut-ref=“myPointcut”/>
- 应用场景:可以修改方法的返回值
1.3.3 最终通知
- 执行时机:目标对象方法之后执行通知,有没有异常都会执行
- 配置文件:<aop:after method=“after” pointcut-ref=“myPointcut”/>
- 应用场景:例如像释放资源
1.3.4 环绕通知
- 执行时机:目标对象方法之前和之后都会执行。
- 配置文件:<aop:around method=“around” pointcut-ref=“myPointcut”/>
- 应用场景:事务、统计代码执行时机
1.3.5 异常通知
- 执行时机:在抛出异常后通知
- 配置文件:<aop:after-throwing method=" afterThrowing " pointcut- ref=“myPointcut”/>
- 应用场景:包装异常
二、使用注解和XML实现
2.1 编写切面类
注意不是通知类,因为该类中可以指定切入点. 使用@Aspect 注解, @Component
5种通知类型分别对应不同的注解,before, around, …
@Component("myAspect")
@Aspect
public class MyAspect {
private static final String pcut = "execution(* *..*.*ServiceImpl.*(..))";
// @Before(value="execution(* *..*.*ServiceImpl.*(..))")
@Before(value="MyAspect.fn()")
public void before() {
System.out.println("这是注解方式的前置通知");
}
@AfterReturning(pcut)
public void after() {
System.out.println("这是注解方式的后置通知");
}
// 通过Pointcut 定义了一个通用的切入点
@Pointcut("execution(* *..*.*ServiceImpl.*(..))")
public void fn() {}
// Around 通知 需要指定joinPoint, 调用目标方法
@Around(value="execution(* *..*.*ServiceImpl.*(..))")
public Object aroundAdvice(ProceedingJoinPoint joinPoint){
object rtValue = null;
try {
// 前置
object[] args = joinPoint.getArgs();
joinPoint.proceed(args);
// 后置
} catch (java.lang.Exception e) {
e.printStackTrace();
} finally {
}
}
}
配置切面类,component-scan 用来扫描 component
<context:component-scan base-package="com.spring"/>
开启AOP自动代理
<!-- 开启aspectj的自动代理,用于AOP的注解方式 -->
<aop:aspectj-autoproxy/>
2.2 环绕通知 Around 注解需注意指定 joinPoint
2.3 定义通用切入点
使用@PointCut注解在切面类中定义一个通用的切入点,其他通知可以引用该切入点。
三、使用纯注解
对未使用注解的部分使用等价注解替换
@Configuration
@ComponentScan(basePackages="com.kkb")
@EnableAspectJAutoProxy
public class SpringConfiguration {
}