AOP是什麼?
AOP是OOP的延續,是Aspect Oriented Programming的縮寫,意思是面向方面編程。AOP實際是GoF設計模式的延續,設計模式孜孜不倦追求的是調用者和被調用者之間的解耦,AOP能夠說也是這種目標的一種實現。
面向方面編程 AOP(Aspect Oriented Programming)是一種「關注點(Concern)」分離技術,經過運用「方面(aspect)」這種程序設計單元,容許開發者使用結構化的設計和編碼,反映出其對系統的認識方式。AOP使設計和編碼更加模塊化、更加具結構化,從而使關注點局部化而不是分散於整個系統中。同時,須要定義好關注點和系統其餘部分的接口,從而真正達到「分離關注點,分而治之」的目的。spring
一、AOP終級目標
AOP終級目標就是能以更天然、更靈活的方式模擬現實世界,從原始的機器語言到過程語言再到面向對象的語言,編程語言一步步地用更天然的方式描述軟個把。AOP是軟件開發思想的下一個產物,但AOP的出現並非要徹底代替OOP,而僅僅是做爲OOP的有益補充。
二、AOP 解決緊密耦合的難題
許多 Java 開發人員已經接受了面向方面編程(AOP)的非強制性風格和靈活性,特別是在用於創建高度鬆散和可擴展的企業系統時
在將商業需求轉換成軟件功能的快速開發週期中,面向方面是一種能夠利用的強有力的設計原理。經過將首要的設計重點從面向對象編程(OOP)的傳統化特性轉移出來,AOP 和設計原理容許軟件架構師用一種和麪向對象至關而又互補的方式來考慮設計。
三、分散關注 將通用需求功能從不相關類之中分離出來;同時,可以使得不少類共享一個行爲,一旦行爲發生變化,沒必要修改不少類,只要修改這個行爲就能夠。
四、AOP超越面向對象編程和設計,正在成爲軟件開發的下一個聖盃。
使用AOP,你能夠將處理aspect的代碼注入主程序,一般主程序的主要目的並不在於處理這些aspect。AOP能夠防止代碼混亂。
AOP 與全部 Java 開發人員所使用的面向對象設計和編程並不矛盾,也不會替代它,相反,會對其給予補充。AOP 能夠當作開發人員和研究團體超越軟件工程中的面向對象編程(OOP)天然而然的下一步。 數據庫
Aspect(切面): 是通知和切入點的結合,通知和切入點共同定義了關於切面的所有內容---它的功能、在什麼時候和何地完成其功能
joinpoint(鏈接點):所謂鏈接點是指那些被攔截到的點。在spring中,這些點指的是方法,由於spring只支持方法類型的鏈接點.
Pointcut(切入點):所謂切入點是指咱們要對那些joinpoint進行攔截的定義.
通知定義了切面的」什麼」和」什麼時候」,切入點就定義了」何地」.
Advice(通知):所謂通知是指攔截到joinpoint以後所要作的事情就是通知.通知分爲前置通知,後置通知,異常通知,最終通知,環繞通知(切面要完成的功能)
Target(目標對象):代理的目標對象
Weaving(織入):是指把切面應用到目標對象來建立新的代理對象的過程.切面在指定的鏈接點織入到目標對象
Introduction(引入):在不修改類代碼的前提下, Introduction能夠在運行期爲類動態地添加一些方法或Field.express
代碼實例:編程
1)新建Book的pojo類設計模式
package com.spring._0416service; public class Book { private String bookeName; private String author; private double price; public Book() { } public String getBookeName() { return bookeName; } public void setBookeName(String bookeName) { this.bookeName = bookeName; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } }
2)這裏模擬數據庫的新增方法架構
package com.spring._0416service; public interface BookService { public void addBook(Book book); } package com.spring._0416service; public class BookServiceImpl implements BookService{ @Override public void addBook(Book book) { System.out.println(book.getBookeName()+" "+book.getAuthor()+" "+book.getPrice()); } }
3)準備事務切面類app
package com.spring._0416service; /** * 事務切面類 * */ public class TransAspect { public void open(){ System.out.println("開啓事務"); } public void commit(){ System.out.println("提交事務"); } }
4)配置applicationContext.xml編程語言
1.注入bookService和transAspectide
<bean id="bookService" class="com.spring._0416service.BookServiceImpl"/> <bean id="transAspect" class="com.spring._0416service.TransAspect"/>
2.配置切面 (前置通知和後置通知)模塊化
<!--配置切面--> <aop:config> <!--order 用來多個排序--> <aop:aspect order="1" ref="transAspect"> <!--第一顆*表明任意返回值類型,第三顆*表明類的任意方法,兩個.表明 任意參數--> <aop:pointcut id="cutPoint" expression="execution(* com.spring._0416service.*.*(..))"/> <aop:before method="open" pointcut-ref="cutPoint"/> <aop:after method="commit" pointcut-ref="cutPoint"/> </aop:aspect> </aop:config>
5)測試
import com.spring._0416service.Book; import com.spring._0416service.BookService; import com.spring._0416service.BookServiceImpl; import org.junit.Before; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class BookServiceTest { private BookService bookService; @Before public void init(){ ApplicationContext act=new ClassPathXmlApplicationContext("applicationContext.xml"); bookService=act.getBean("bookService",BookService.class); } @Test public void test(){ Book book=new Book(); book.setAuthor("海明威"); book.setBookeName("喪鐘爲誰而鳴"); bookService.addBook(book); } }
結果:
1)新建user的pojo類
package com.spring.homework1; public class User { private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
2)service兩個方法:查看view()方法和刪除delete()方法
package com.spring.homework1; public interface UserService { public void view(User user); public void delete(User user); } package com.spring.homework1; public class UserServiceImpl implements UserService{ public void view(User user) { System.out.println(user.getUsername()+"查看該網站"); } public void delete(User user) { System.out.println(user.getUsername()+"執行刪除"); } }
3)設置兩個切面類(getArgs()方法:獲取鏈接點方法運行時的入參列表,proceed()方法:經過反射執行目標對象的鏈接點處的方法,就是放行的意思)
package com.spring.homework1; import org.aspectj.lang.ProceedingJoinPoint; public class UserAspect1 { public Object check1(ProceedingJoinPoint point) throws Throwable { Object result=null; User user= (User) point.getArgs()[0]; if(user.getUsername().equals("ling")&&user.getPassword().equals("wutongshu")){ result= point.proceed(); System.out.println("當前的方法:"+point.getSignature().getName()+" check1"); }else if(user.getUsername().equals("miao")&&user.getPassword().equals("wutongshu")){ System.out.println("當前的方法:"+point.getSignature().getName()+" check1"); result=point.proceed(); }else{ System.out.println("sss權限不夠,請從新登陸"); System.out.println("當前的方法:"+point.getSignature().getName()+"check1"); } return result; } }
package com.spring.homework1; import org.aspectj.lang.ProceedingJoinPoint; public class UserAspect2 { public Object check2(ProceedingJoinPoint point) throws Throwable { Object result=null; User user= (User) point.getArgs()[0]; if(user.getUsername().equals("ling")&&user.getPassword().equals("wutongshu")){ System.out.println("當前的方法:"+point.getSignature().getName()+"check2"); result= point.proceed(); }else if(user.getUsername().equals("miao")&&user.getPassword().equals("wutongshu")){ System.out.println("當前的方法:"+point.getSignature().getName()+"check2"); System.out.println("權限不夠,沒法刪除"); }else{ System.out.println("ss權限不夠,請從新登陸"); System.out.println("當前的方法:"+point.getSignature().getName()+"check2"); } return result; } }
4)配置xml (around 環繞通知)
<bean id="userService" class="com.spring.homework1.UserServiceImpl"/> <bean id="userAspect1" class="com.spring.homework1.UserAspect1"/> <bean id="userAspect2" class="com.spring.homework1.UserAspect2"/> <aop:config> <aop:aspect order="1" ref="userAspect1"> <aop:pointcut id="user1Point" expression="execution(* com.spring.homework1.UserServiceImpl.view(..))"/> <aop:around method="check1" pointcut-ref="user1Point"/> </aop:aspect> <aop:aspect order="2" ref="userAspect2"> <aop:pointcut id="user2Point" expression="execution(* com.spring.homework1.UserServiceImpl.delete(..))"/> <aop:around method="check2" pointcut-ref="user2Point"/> </aop:aspect> </aop:config>
5)測試
import com.spring.homework1.User; import com.spring.homework1.UserService; import org.junit.Before; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class UserServiceTest { private UserService userService; @Before public void init(){ ApplicationContext act=new ClassPathXmlApplicationContext("applicationContext.xml"); userService=act.getBean("userService",UserService.class); } @Test public void test(){ User user=new User(); user.setUsername("ling"); user.setPassword("wutongshu"); userService.view(user); userService.delete(user); } }
結果:
當咱們切換成只能查看的用戶
或者二者權限都沒有的用戶