一、概念:
AOP(Aspect Oriented Programming)即面向切面编程(也叫面向方面),可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。
主要的功能是:日志记录,性能统计,安全控制,事务处理,异常处理等等。
主要的意图是:将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。
换句话说就是把独立的服务单独拿出来,当流程执行到该服务时转到拿出来的专门的模块(切面)里执行。
二、示例
该示例为在添加用户前需要进行日志记录,我们通过该示例可以了解AOP是如何实现在不修改源代码的情况下给程序动态统一添加功能的。
我们先来看看不使用AOP的情况下(即不进行日期记录,但是由spring框架实现),如何实现操作:
1.环境搭建
引入相关jar包
SPRING_HOME/dist/spring.jar
SPRING_HOME/lib/log4j/log4j-1.2.14.jar
SPRING_HOME/lib/jakarta-commons/commons-logging.jar
引入配置文件applicationContext.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:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<bean id="userManager" class="com.bjpowernode.spring.UserManagerImpl"/>
</beans>
2.代码:
UserManager.java
package com.dan.spring;
public interface UserManager {
public void addUser(String username, String password);
}
UserManagerImpl.java
package com.dan.spring;
public class UserManagerImpl implements UserManager {
public void addUser(String username, String password) {
System.out.println("---------UserManagerImpl.add()--------");
}
}
Client.java
package com.dan.spring;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Client {
public static void main(String[] args) {
BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");
UserManager userManager = (UserManager)factory.getBean("userManager");
userManager.addUser("赵丹丹", "123");
}
}
当我们使用AOP(进行日志记录)后,需要添加LogHandler类及相关jar包(SPRING_HOME/lib/aspectj/*.jar),前面编写好的类不需要改动,只需改一下配置文件即可:
LogHandler.java
package com.dan.spring;
public class LogHandler {
private void addLog() {
System.out.println("-------Log-------");
}
}
applicationContext.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:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<bean id="userManager" class="com.bjpowernode.spring.UserManagerImpl"/>
<bean id="logHandler" class="com.bjpowernode.spring.LogHandler"/>
<aop:config>
<!-- 声明切面类为logHandler -->
<aop:aspect id="logAspect" ref="logHandler">
<!-- 以add开头的方法 -->
<aop:pointcut id="addAddMethod" expression="execution(* add*(..))"/>
<!-- 在调用切入点addAddMethod前执行logHandler的addLog方法 -->
<aop:before method="addLog" pointcut-ref="addAddMethod"/>
</aop:aspect>
</aop:config>
</beans>
三、AOP相关概念
下面的是对上面示例添加AOP的过程展示并提到了几个相关的概念:
1.Cross Cutting Concern(横切关注点)
即检查安全性具体操作,针对该示例即为添加方法
是一种独立服务,它会遍布在系统的处理流程之中
2.Aspect(切面)
对横切性关注点的模块化。
3.Advice(通知)
对横切性关注点的具体实现。
4.Pointcut(切入点)
即限制哪些方法需要进行检查安全性,针对该示例即为只应用到add*类的方法上。
它定义了Advice应用到哪些JoinPoint上,对Spring来说是方法调用。
5.JoinPoint(连接点)
即需要调用的实际方法,针对该示例即为addUser。
Advice在应用程序上执行的点或时机,Spring只支持方法的JoinPoint,这个点也可以使属性修改,如:Aspecj(也是对AOP的一个实现)可以支持。
6.Weave(织入)
将Advice应用到Target Object上的过程叫织入,Spring支持的是动态织入。
7.Target Object(目标对象)
Advice被应用的对象,即被代理的类,针对该示例即为UserManager。
8.Proxy(AOP代理)
即代理类,Spring AOP默认使用JDK的动态代理,它的代理是运行时创建,也可以使用CGLIB代理。
9.Introduction(引入)
可以动态的为类添加方法。
通过以上介绍,我们对AOP有了一定的认识,我前面写过一篇博客是关于JDK动态代理的介绍,而AOP的底层实现就是JDK的动态代理,AOP实现了在不更改代码的情况下动态增添功能(扩展性的完美体现),成功地对程序进行了解耦。