什么是AOP
Aspect Oriented Programming 面向切面编程 或者 面向方面编程
它是对面向对象的一个扩展
可以不修改原有代码的情况下 给原有的逻辑增加功能
降低了共通业务逻辑 和 原有逻辑的耦合度 因为共同业务逻辑可以通过配置手段加入到原有逻辑中
AOP 中涉及到概念
切面 Aspect 封装共通业务逻辑的
连接点 JoinPoint 共通业务逻辑所要嵌入的位置 一般封装了方法的信息
切点 Pointcut 它是一堆连接点 可以看成连接点的集合 (切点表达式)
目标 Target 要嵌入共通业务逻辑的对象
代理 Proxy 被增强之后的目标对象
通知 Advice 时机 目标方法调用之前 目标方法调用之后 目标方法调用前后
目标方法最终 目标方法出现异常
切面 --- 通知 --- 切点
Spring 实现 AOP 的步骤
1 建立一个项目 导入jar包(ioc aop) 拷贝配置文件到src下
2 编写一个银行账户的服务类 有登录 和 注册两个方法
这两个方法使用伪代码即可
3 在配置文件中配置这个服务器类 然后通过容器获取服务类对应的对象 测试方法调用
4 在不修改服务类代码的情况下 让服务类对应的方法调用前输出 ******
a.定义一个切面类 里面定义输出****** 的方法
b.在配置文件中 配置切面类型的对象
<bean id="logAspect" class="com.xdl.aspect.LogAspect"></bean>
c.在Spring 配置文件中 写 AOP 的配置
<aop:config>
<aop:aspect ref="logAspect">
<aop:before method="print" pointcut="bean(bankService)" />
</aop:aspect>
</aop:config>
切面 通知 切点
切点表达式的写法
1 bean 限定表达式
bean(spring容器中id表达式) 支持统配 如 bean(*Account)
2 类型限定表达式
within(表达式) 表达式的写法 是最后一部分必须是 类型 com.xdl.dao.BankDaoImpl
对BankDaoImpl 这个类型 对应的所有方法都切入共通业务逻辑。
com.xdl.dao.* dao包下所有的类型 对应的方法都将被切入共通业务逻辑
com..* com 包下所有的类型 以及 com的子包下所有的类型 对应的方法都将被切入共通业务逻辑
<aop:before method="printSysTime" pointcut="within(com..*)"/>
3 方法限定表达式
execution(方法限定)
方法限定的格式
权限修饰 返回值类型 方法名(参数列表) throws 异常
其中 返回值类型 方法名() 是必须的
<aop:before method="printSysTime" pointcut="execution(* *())"/>
AOP 中的五种通知类型
<aop:before 前置通知 目标方法调用之前调用
<aop:after 最终通知 目标方法调用后 一定会调用
<aop:after-returning 后置通知 目标方法调用之后调用
<aop:after-returning method="printSysTime" pointcut="execution(* *())"/>
<aop:after-throwing 异常通知 目标方法调用出现异常 采用调用
<aop:after-throwing method="printSysTime" pointcut="execution(* *())"/>
<aop:around 环绕通知 目标方法调用前后都调用
使用标注形式的AOP 给方法增加功能
1 编写一个切面类 定义切面方法
2 开启标注形式的 aop
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
proxy-target-class="false" 使用SUN公司的代理机制
proxy-target-class="true" 使用CGLIB的代理机制
3 创建切面组件 @Component 然后普通 切面类变成真正的切面
@Aspect 在切面方法上 对应通知对应的标注 并在标注中写切点表达式即可
@Component
@Aspect
public class LogAspect {
@After("bean(bankDao)")
public void printData() {
Date date = new Date();
long times = date.getTime();//时间戳
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateString = formatter.format(date);
System.out.println(dateString+"@"+times);
}
}
AOP 中五种通知 对应的标注
前置通知 @Before
后置通知 @AfterReturning
最终通知 @After
异常通知 @AfterThrowing
环绕通知 @Around