AOP(Aspect-Oriented Programming -面向切面编程)其实是OOP(Object-Oriented Programing -面向对象编程) 思想的补充和完善。
我们知道,面向对象的特性是:“多态”,“继承” ,“封装”,对事物进行了抽象和封装,以此建立了一种对象的层次结构,它强调一种完整的自上而下的关系。不过 OOP 的设计允许开发者定义事务的纵向关系,并不适合定义横向关系,比如在记录日志的功能,安全性,异常处理和透明的持续性也都是如此,我们将这种散布在周围无关的代码称之为 横切,也即是 面向切面 编程AOP(Aspect Oriented Programming)。
一、 AOP的基本概念
aspect(切面): 通常是以类的形式出现 ,在此切面中定义 切入点和通知
join point(连接点): 是程序执行中的一个精确执行点,例如类中的一个方法。它是一个抽象的概念,在实现AOP时,并不需要去定义一个join point。
point cut(切入点): 本质上是一个捕获连接点的结构。在AOP中,可以定义一个point cut,来捕获相关方法的调用。
advice(通知增强): 是point cut的执行代码,是执行“方面”的具体逻辑。

要想更清楚的了解AOP的运行过程,就必须知道在java中 ,反射 的原理 ,springAOP 也是利用了反射的原理来对类进行操作。
在 spring 中,配置AOP的方式有两种,一种是在XML中配置,另一种是使用注解的方式配置。
1.在XMl配置 我定义的xml文件名为 MyContext.xml

<?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"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="
		http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context.xsd
		http://www.springframework.org/schema/aop
		http://www.springframework.org/schema/aop/spring-aop.xsd
		http://www.springframework.org/schema/mvc
		http://www.springframework.org/schema/mvc/spring-mvc.xsd"
		>
	<!-- 使用注解驱动 -->
	<mvc:annotation-driven />
	<!-- 开启包扫描 -->
	<context:component-scan base-package="com.spring.advice"/>
	<!-- 开启代理模式 -->
	<aop:aspectj-autoproxy proxy-target-class="true"/>
	<bean id="logAdvice" class="com.spring.advice.LogAdvice"></bean>
	<bean id="userDao" class="com.spring.dao.UserDao"></bean>
	<aop:config>
		<aop:aspect ref="logAdvice">
			<aop:before method="log" pointcut="target(com.spring.dao.UserDao) and execution(* update(..))"/>
			<aop:around method="around" pointcut="target(com.spring.dao.UserDao) and execution(* update(..))"/>
			<aop:after method="after" pointcut="target(com.spring.dao.UserDao) and execution(* update(..))"/>
		</aop:aspect>
	</aop:config>

aop:aspect 表示的是切面,通常是一个类 ,ref 链接到 初始化的bean中 ,也就是<bean id="logAdvice" class="com.spring.advice.LogAdvice"></bean>
aop:before 表示执行方法 之前 method 指的是对应的方法名 ,pointcut 表示切入点, target(目标类路径),execution(* update(…)); 第一个*号表示通配符 表明返回任意类型 ,update 表示执行的 目标函数名 , (…) 指的是 传递的参数个数,这里不限制,抽象了,一般来说都要写具体,比如(int ,string)
<aop:around method="around" pointcut="target(com.spring.dao.UserDao) and execution(* update(..))"/> <aop:after method="after" pointcut="target(com.spring.dao.UserDao) and execution(* update(..))"/>
aop:around 和 aop:after 分别表示 周围 和之后,具体的实现跟 aop:aspect 一样。
2.使用注解的方式配置
在spring中,已经为我们定义好了 AOP的注解(
@Aspect, @Component :需要在通知(增强)类中使用
@Before :在被代理对象的方法前先调用 (前置通知)
@After :在被代理对象的方法调用后再执行(后置通知)
@Around :将被代理对象的方法封装起来,用环绕通知取代)
@AfterReturning 在被代理对象的方法正常返回后调用要求,被代理对象的方法在执行过程中没有出现异常
@AfterThrowing 在被代理对象的方法抛出异常后调用要求,被代理对象的方法在执行过程中出现异常
我们只需要在类和方法名前加上注解就好了,具体代码如下:
LogAdvice.java

@Component
@Aspect
public class LogAdvice {
	// 表示记录 UserDao 下的所有方法 都执行
	@Before("execution(* com.spring.advice.UserDao.*(..))")
	public void log(JoinPoint  jp) {
		System.out.println(new Date() +"更新日志");
	}
	//@Around 利用的java的反射原理机制执行  pjp.proceed(); 方法
	@Around("execution(* com.spring.advice.UserDao.insert(int,String))")
	public Object around(ProceedingJoinPoint pjp) throws Throwable {
		Object result =null;
		result = pjp.proceed();
		return result;
	}

	@After("execution(* com.spring.advice.UserDao.*(..))")
	public void after() {
		System.out.println(new Date() +"更新完毕");
	}

UserDao.java

@Component
public class UserDao {
	public void insert(int n , String password) {
		System.out.println("插入数据(int,String)"+ n +" , "+password);
	}
}

Test.java

import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
	public static void main(String[] args) throws Exception {
		ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("MyContext.xml");
		UserDao ud = (UserDao) ctx.getBean("userDao");
		ud.insert(1, "10086");
	}
}

结果:
springAOP的思想和设计以及实现-LMLPHP
这就是所谓的面向切面编程,它不破坏方法的完整性,有兴趣的小伙伴可以去研究一下设计模式中的代理模式,相信会使你对AOP的机制更加的了解。

12-02 10:17