AOP技术个人认为是能够完善(改善)面向对象编程OOP。为什么这么说,我们得先从AOP的概念说起,然后通过一段简单的例子加以佐证。这样子大家就可以慢慢地了解AOP
1. AOP概念
- AOP为Aspect Oriented Programming的缩写,含义:面向切面的编程。
2. AOP主要作用是什么,为什么要提出AOP概念,AOP技术到底能用到哪些实际的开发场景里面去
- AOP技术主要的用做在日志记录,性能统计,安全控制,事务处理,异常处理等等
- 例如日志功能,日志代码往往横向地散布在所有对象层次中。而这种散布在各处的无关的代码被称为横切(cross cutting),在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用
- AOP技术恰恰相反,它利用一种称为"横切"的技术,将公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面
- 所谓"切面",简单说就是那些与业务无关,但是所有业务模块都要用到的公共代码,我们就把这些功能类似的公共代码封装成一个Java类,这个Java类也就叫做"切面"
- 有了AOP这种技术,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。
3. AOP核心概念
- 切面,Aspect:其实就是我们需要定义的AOP类,它对功能类似的代码进行封装。例如:日志类,安全控制类,事务管理类等
- 关注点:对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点
- 连接点,Join Point:程序执行过程中的某一点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法
- 切入点,Pointcut:一系列连接点的集合,对连接点进行拦截的定义
- 通知(建议,Advice):AOP框架在特定的连接点上执行的动作(代码),通知分为前置、后置、异常、最终、环绕通知五类
- 目标对象,Target object:要被代理的对象
- 织入(weave):将切面应用到目标对象并导致代理对象创建的过程
- 引入,Introduction:简单说就是AOP中的方法
4. Spring创建代理的规则有两种
- 默认使用JDK动态代理,为任何接口实例创建代理
- 类代理,当需要代理一个类而不是接口的时候,Spring会采用CGLIB方式完成
5. Spring AOP的代码实现步骤
- 定义切面,即AOP类
- 定义通知
- 定义切入点语法
6. 下面我就来完成一个demo来实现一个基础的Spring AOP(简单的日志记录例子),这里我们采用注解的方式来实现。后面我们也给介绍基于XML文件配置的AOP
- 创建AOP类
package com.spring.aop; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; @Aspect public class LogAop { @Before("execution(public void com.spring.dao.impl.StudentDaoImpl.*(..))") public void logBefore() { System.out.println("方法执行之前加载日志"); } }
- 创建一个StudentDao接口
package com.spring.dao; public interface StudentDao { public void insert(); }
- 创建实现StudentDao接口的类
package com.spring.dao.impl; import com.spring.dao.StudentDao; public class StudentDaoImpl implements StudentDao { @Override public void insert() { System.out.println("method insert"); } }
- 创建一个Service类
package com.spring.services; import com.spring.dao.StudentDao; public class StudentServices { private StudentDao dao; public void setDao(StudentDaodao) { this.dao = dao; } public void insert() { dao.insert(); } }
- 创建一个JUnit测试类
package com.spring.junit; import static org.junit.Assert.*; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.spring.dao.StudentDao; import com.spring.services.StudentServices; public class Test_AOP { @Test public void testInsert() { ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); StudentServices ss = (StudentServices) ac.getBean("studentServices"); ss.insert(); } }
- 创建bean-aop-annotation.xml文件,此文件开启一个AOP切面注解功能的配置文件
<?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:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> <bean id="studentServices" class="com.spring.services.StudentServices"> <property name="dao" ref="studentDao"></property> </bean> <bean id="studentDao" class="com.spring.dao.impl.StudentDaoImpl"> </bean> <bean id="logAop" class="com.spring.aop.LogAop"></bean> </beans>