一、AOP介绍
1.1 AOP:面向切面编程
在程序原有纵向执行流程中,针对某一个或某一些方法添加通知,形成横切面的过程就叫做面向切面编程
1.2 出现的必要性
正产的程序的执行流程都是纵向执行流程,即代码从上到下执行。而AOP是在原有纵向执行流程中添加横切面,不需要修改原有的程序代码
1.3 AOP的优点
1.高扩展性
2.原有功能相当于释放了部分逻辑,让职责更加明确
1.4常用概念
- 原有功能:切点(pointcut)
- 前置通知:在切点之前执行的功能,before advice
- 后置通知:在切点之后之心的功能,after advice
- 异常通知:如果切点在执行过程中出现异常,就会触发异常通知,throws advice
- 切面:就是编写的AOP或者方面
- 织入:把切面嵌入到原有功能的过程叫做织入
二、AOP中几种通知类型
1.什么是通知?
所谓通知就是决定了切面什么时间节点去工作的定义
2.通知类型
- before 前置通知(在调用目标代码之前执行)
- after 后置通知(在调用目标代码之后执行)
- around 环绕通知(在调用目标代码之前、之后都执行)
- throwadvice 异常通知(当目标代码出现异常后执行)
3.切面至少要具备一种通知类型
三、AOP四种实现方式
在Spring中配置一个AOP的方式一共四种:
1、动态代理方式:通过Spring提供的代理对象实现AOP的配置
1.需要导入Spring-aop.jar
2.编写目标代码
/**
* 业务层
* @author Administrator
*
*/
public class UserServiceImpl implements UserService {
@Override
public void addUser(String str) {
System.out.println("AddUser...................."+this);
}
}
编写切面,定义通知
MethodBeforeAdvice:spring框架提供的一个前置通知定义
public class MyAOP implements MethodBeforeAdvice {
/**
* @param arg0:目标方法的方法对象
* @param arg1:目标方法的参数列表
* @param arg2:目标对象
*/
@Override
public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
System.out.println(arg0.getName());
System.out.println(arg1[0]);
System.out.println(arg2);
System.out.println("Before................");
}
}
配置切面
<!-- 配置目标对象 -->
<bean id="userService" class="com.tinner.service.impl.UserServiceImpl"/>
<!-- 配置AOP -->
<bean id="myAOP" class="com.tinner.aop.MyAOP"></bean>
<!-- 织入 -->
<bean id="userServiceAOP" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 配置目标 -->
<property name="target">
<ref bean="userService"/>
</property>
<!-- 配置目标实现的接口 -->
<property name="proxyInterfaces">
<value>com.tinner.service.UserService</value>
</property>
<!-- 配置aop -->
<property name="interceptorNames">
<list>
<value>myAOP</value>
</list>
</property>
</bean>
异常通知
public class MyAOPThrow implements ThrowsAdvice {
// 通知方法,需要按照这种格式书写
// @param method
// 可选:切入的方法
//@param args
// 可选:切入的方法的参数
// @param target
// 可选:目标对象
// @param throwable
// 必填 : 异常子类,出现这个异常类的子类,则会进入这个通知。
public void afterThrowing(Method method,Object[] args,Object obj,Throwable t){
System.out.println("出错了。。。。。。。。。。。。。。");
}
}
2、基于Spring整合的AspectJ
导入jar包
编写切面
该切面的编写和使用动态代理的方式没有区别
public class MyAOP implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("AspectJ.............Before");
}
}
在spring的配置文件的开头中开启命名空间
<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
http://www.springframework.org/schema/aop/spring-aop.xsd">
在Spring的配置文件中通过命名空间配置AOP
<!-- 配置切面 -->
<bean id="myAop" class="com.tinner.aopaspectj.MyAOP"/>
<!-- 目标 -->
<bean id="userService" class="com.tinner.service.impl.UserServiceImpl"/>
<!-- 织入 -->
<aop:config>
<aop:pointcut expression="execution(* com.tinner.service.impl.UserServiceImpl.*(..))" id="mycut"/>
<!--
advice-ref= 关联切面
pointcut-ref 切点
-->
<aop:advisor advice-ref="myAop" pointcut-ref="mycut"/>
</aop:config>
3、纯POJO的方式
在execution标识中,添加 and args(name)
<aop:before arg-names=”name”>
<aop:after-returning>:调用目标执行成功时才会执行拦截器
<aop:after>:无论目标执行是否成功,该拦截器都要执行
<aop:config expose-proxy="true"> :选用干什么方式来创建代理
4、基于annotation方式
主要是用注解的方式autowired