Spring AOP:面向切面编程
在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,
通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。
AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,
利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,
提高程序的可重用性,同时提高了开发的效率。
主要功能
日志记录,性能统计,安全控制,事务处理,异常处理等等。
通知:
1.前置通知 Before
2.后置通知 After_returning
3. 异常通知 After_throwing
4.最终通知 After
5.环绕通知 Around
连接点:程序中需要动态织入
代码的一个点。(被切类的方法)切点:会匹配通知所要织入的一个或多个
连接点,解决了在哪些类和方法的
连接点上执行通知的问题。(被切类实现通知的方法切面: 通知和切点的结合(添加通知的类)引入:引入允许我们向现有的类
添加新方法或属性,使程序
具有动态性。(切点添加通知的过程)
基本实现XML:
1.AOP坐标:
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.7</version>
</dependency>
2.注入类
<!--以此注入类-->
<bean id="serviceImp" class="com.apesource.service.AccountServiceImp"></bean>
<bean id="loggerUtil" class="com.apesource.logger.LoggerUtil"></bean>
3.配置
<!--开启aop配置
<aop:config>===========================>aop配置
<aop:aspect id="切面的标识" ref="通知方法所在的类">=========>aop切面
<aop:pointcut id="切点的标识" expression="切点的通配符表达式"/>>=====>aop切点
<aop:before method="方法" pointcut-ref="切点的引用"></aop:before>============>aop通知
expression="业务类中的所有方法" 语法:expression="execution(方法修饰符 返回值类型 包.包.包.类.方法名(参数列表))" 规范语法: 参数使用".."代表任意个数任意类型 * *..*.*(..) 参数规范写法 基本类型写关键字int 引用类型写全路径java.lang.String
<aop:config>
<aop:aspect id="mian" ref="logUtil">
<aop:pointcut id="dian" expression="execution(* *..service.*.*(..))"></aop:pointcut>
<!-- <aop:before method="before" pointcut-ref="dian"></aop:before>-->
<!-- <aop:after-returning method="after_runtime" pointcut-ref="dian"></aop:after-returning>-->
<!-- <aop:after-throwing method="execution" pointcut-ref="dian"></aop:after-throwing>-->
<!-- <aop:after method="after" pointcut-ref="dian"></aop:after>-->
<aop:around method="arround" pointcut-ref="dian"></aop:around>
</aop:aspect>
</aop:config>
4.补充:环绕通知需要 在方法内设置
public Object around(ProceedingJoinPoint point){
//切点的返回值
Object result=null;
try {
//前置通知
System.out.println("前置通知启动"+new Date());
//指代切点的参数
Object[] args = point.getArgs();
//指代切点(方法)
result = point.proceed(args);
//后置通知
System.out.println("后置通知启动"+new Date());
} catch (Throwable throwable) {
throwable.printStackTrace();
//异常通知
System.out.println("异常通知启动"+new Date());
} finally {
//最终通知
System.out.println("最终通知启动"+new Date());
}
return result;
}
注解+XML:
1.注入类和切面类 (@Component)
2.标明切面(@Aspect)
3.创建连接点方法并标明(@Pointcut(value = "execution( ...(..))") )
@Pointcut(value = "execution(* *..*.*(..))")
//任意返回值类型个数 任意包下的任意类的任意方法的(任意参数类型个数)
public void dian(){
}
4.在通知方法上标明(@Before(value="连接点方法名"))
前置通知
@Before("dian()")
后置通知
@AfterReturning(value = "dian()")
异常通知
@AfterThrowing("dian()")
最终通知
@After("dian()")
环绕通知
@Around("dian()")
public Object around(ProceedingJoinPoint point){
Object result=null;
try {
System.out.println("前置通知启动");
Object[] args = point.getArgs();
result = point.proceed(args);
System.out.println("后置通知启动");
} catch (Throwable throwable) {
throwable.printStackTrace();
System.out.println("异常通知启动");
} finally {
System.out.println("最终通知启动");
}
return result;
}
5.在配置文件中开启配置
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>