AOP簡介:java
面向切面的編程(也叫面向方面編程):Aspect Oriented Programming(AOP),是軟件開發中的一個熱點,也是 Spring框架中的一個重要內容。利用AOP能夠對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度下降,提升程序的可重用性,AOP是OOP編程的延續。spring
與OOP的區別:express
面向對象編程主要用於爲同一對象層次的公用行爲建模。它的弱點是將公共行爲應用於多個無關對象模型之間。而這偏偏是面向方面編程適合的地方。有了 AOP,咱們能夠定義交叉的關係,並將這些關係應用於跨模塊的、彼此不一樣的對象模型。AOP 同時還可讓咱們層次化功能性而不是嵌入功能性,從而使得代碼有更好的可讀性和易於維護。它會和面向對象編程合做得很好。編程
舉個例子:app
學生的service類框架
public class StudentServiceImpl implements IStudentService{ @Override public void addStudent(String name) { // TODO Auto-generated method stub System.out.println("姓名:"+name); } }
如今有個需求:在添加方法的邏輯中,添加以前輸出日誌,添加完成以後輸出添加成功日誌,最簡單的方法是:ide
public class StudentServiceImpl implements IStudentService{ @Override public void addStudent(String name) { // TODO Auto-generated method stub //輸出日誌邏輯代碼 System.out.println("姓名:"+name); //添加成功日誌代碼 } }
如今咱們又有別的Service 類也須要一樣的需求。須要修改的類足足有100個(開個玩笑) ,不可能一個個去修改,Service類,並且倆個輸出日誌的代碼在其餘Service類中是同樣的,若是一直複製粘貼對代碼沒有作到可複用性。測試
這個時候AOP就派上用處了。spa
以Spring框架中爲例:代理
spring.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:context="http://www.springframework.org/schema/context" 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-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd"> <context:component-scan base-package="com.younchen.*" /> <bean id="StudentImpl" class="com.younchen.aop.StudentImpl" /> <bean id="DaliyLog" class="com.younchen.aop.DaliyLog"/> <bean id="Log" class="com.younchen.aop.Log"/> <aop:config> <!-- expression 括號 第一個 星號表示 全部返回值類型,第二個星號表示全部類,第三個星號表示全部的方法,括號倆點表示方法參數 --> <aop:pointcut expression="execution(* com.younchen.aop.*.*(..))" id="target" /> <aop:aspect id="Logger" ref="Log"> <aop:before method="beforeAdd" pointcut-ref="target" /> <aop:after method="afterAdd" pointcut-ref="target" /> </aop:aspect> </aop:config> </beans>
在config 標籤中的第一個標籤pointcut是切入點, expression是表達式, 看下括號中的第一個*號,意思是針對於全部的返回類型 ,緊接着是類所在的包名,以後的倆個星號分別表明類名和方法名 ,後面的括號中倆個點表明全部的參數。該標籤的做用是聲明在執行com.younchen.aop這個包下的全部類的全部方法時執行咱們要切入的方法 。
aspect標籤是切面也就是咱們要切入的方法 ref指定咱們的切入方法的類,該標籤中的子標籤 before method的做用是expression表達式中指定的類的方法執行前執行, after method是以後執行。 pointcut-ref 是指定切入點,除了引用的切入點(表達式指定的範圍外) 該切面是不執行的。
未給出的完整代碼:
Log類:
package com.younchen.aop; public class Log { public void beforeAdd(){ System.out.println("準備添加數據"); } public void afterAdd(){ System.out.println("添加完成"); } }
SpringUtil類:
public class SpringUtil { private static ApplicationContext context = null; public static ApplicationContext getApplicationContext() { if (context == null) { context = new ClassPathXmlApplicationContext("spring.xml"); } return context; } public static ApplicationContext getApplicationContext(String path) { return new ClassPathXmlApplicationContext(path); } public static ApplicationContext getAnnotationConfigApplicationContext(String basePackages) { return new AnnotationConfigApplicationContext(basePackages); } }
其餘service類:
public class DaliyLog { public void addLog(){ System.out.println("添加每日日誌"); } }
測試類:
public class Test { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub ApplicationContext applicationContext=(ApplicationContext) SpringUtil.getApplicationContext("springaop.xml"); IStudent studentService=(IStudent) applicationContext.getBean("StudentImpl"); DaliyLog daliyLog=(DaliyLog) applicationContext.getBean("DaliyLog"); studentService.addStudent("麥克米蘭"); System.out.println("-----------------------------------------------------------"); daliyLog.addLog(); } }
執行結果:
準備添加數據 姓名:麥克米蘭 添加完成 ----------------------------------------------------------- 準備添加數據 添加每日日誌 添加完成
以上是簡單一個例子,AOP的原理實際上是動態代理。 切面是被動態代理的類, 在被動態代理時,產生一個新的類,在這個類中除了執行被代理的方法外,還注入了切面的方法。
歡迎指正。