什么是AOP
意为面向切面编程,通过预编译以及运行时动态代理实现程序功能的统一维护的一种技术。简单来说,就是把我们程序中重复的代码抽取出来,在需要执行的时候,使用动态代理的技术,在不修改源码的基础上对已有的方法进行加强。
AOP的作用以及优势
作用: 在程序运行期间,不修改源码对已有方法进行增强
- 优势:
减少重复代码
提高开发效率
维护方便
springAOP中的相关术语
Jointpoint: (连接点)所谓连接点就是那些被拦截到的点。通俗点说,这些点就是方法,因为我们通过动态调用(连接)方法的方式来对方法进行加强。
Pointcut: (切入点)切入点就是我们拦截到的连接点,因为我们不一定要加强所有的方法,被拦截的方法就是切入点,不需要被拦截的方法就只是连接点。
Advice:(通知/增强)也就是拦截到连接点后要做的事情,或者是一个通知或者时加强。
通知分为几种:前置通知,后置通知,异常通知,最终通知,环绕通知
Introduction: (引介)引介是一种特殊的通知,它可以在不修改类代码的前提下,在运行期间为类动态的添加一些方法或者Field
Target:(目标对象)代理的目标对象
Weaving:(织入)是指把增强应用的目标对象来创建新的代理对象的过程。
Proxy:(代理)一个类被织入增强后就产生一个代理对象
Aspect:(切面)是切点和通知的结合
spring基于xml的AOP相关配置
首先创建一个业务类接口,用来模拟三种业务
package com.tianqicode.service;
public interface AccountService {
/**
* 模拟查找账户
*/
public void findAccount();
/**
* 模拟保存账户
*/
public void saveAccount(int i);
/**
* 模拟删除账户
*/
public int deleteAccount();
}
添加这个接口的实现类
package com.tianqicode.service.Impl;
import com.tianqicode.service.AccountService;
public class AccountServiceImpl implements AccountService {
public void findAccount() {
System.out.println("查照账户成功");
}
public void saveAccount(int i) {
System.out.println("保存账户成功");
}
public int deleteAccount() {
System.out.println("删除账户成功");
return 0;
}
}
准备一个日志工具类,来记录业务运行的日志
package com.tianqicode.utils;
/**
* 用于打印日志的工具类,里面提供了公共的代码
*/
public class Logger {
/**
* 用于打印日志,计划让其在切入点方法之前执行
*/
public void printLog() {
System.out.println("开始记录日志");
}
}
- spring中基于xml配置文件的AOP配置步骤
1、把通知的bean也交给spring管理
2、使用aop:config标签表明开始aop的配置
3、使用aop:aspect标签表明配置切面
-----id属性:给切面提供一个唯一的标识
-----ref属性:是指定通知bean的id
4、在aop:aspect标签内部使用对应标签来配置通知的类型
-----aop:before :表示配置前置通知
-----method:表示指定类中哪个方法是前置通知
-----pointcut属性:用于指定切入点表达式,该表达式的含义是指对业务层中哪个方法增强。
-----切入点表达式的写法:
----------关键字:execution(表达式)
---------------表达式标准写法:访问修饰符 返回值 包名.包名…类名.方法名(参数列表)
<?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
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 配置service bean -->
<bean id="accountService" class="com.tianqicode.service.Impl.AccountServiceImpl"></bean>
<!-- 配置通知bean -->
<bean id="logger" class="com.tianqicode.utils.Logger"></bean>
<aop:config>
<aop:aspect id="logAdvice" ref="logger">
<aop:before method="printLog" pointcut="execution(public void com.tianqicode.service.Impl.AccountServiceImpl.saveAccount())"></aop:before>
</aop:aspect>
</aop:config>
</beans>
这时候简单的配置就完成了
编写一个测试类
package com.tianqicode;
import com.tianqicode.service.AccountService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractXmlApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class test {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
AccountService accountService = (AccountService) ac.getBean("accountService");
accountService.findAccount();
}
}
运行测试类,发现日志成功的在业务运行之前打印了。