概念:html
切面(aspect):用來切插業務方法的類。
鏈接點(joinpoint):是切面類和業務類的鏈接點,其實就是封裝了業務方法的一些基本屬性,做爲通知的參數來解析。
通知(advice):在切面類中,聲明對業務方法作額外處理的方法。
切入點(pointcut):業務類中指定的方法,做爲切面切入的點。其實就是指定某個方法做爲切面切的地方。
目標對象(target object):被代理對象。
AOP代理(aop proxy):代理對象。java
AOP通知類型:
前置通知(before advice):在切入點以前執行。
後置通知(after returning advice):在切入點執行完成後,執行通知。
環繞通知(around advice):包圍切入點,調用方法先後完成自定義行爲。
異常通知(after throwing advice):在切入點拋出異常後,執行通知git
依賴包:spring
<dependencies> <!-- https://mvnrepository.com/artifact/org.springframework/spring-context --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.6.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.8.10</version> </dependency> <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.10</version> </dependency> <!-- https://mvnrepository.com/artifact/cglib/cglib --> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.2.5</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-aop --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>4.3.6.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.3.6.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-tx --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>4.3.6.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>4.3.6.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-core --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.3.6.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/log4j/log4j --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> </dependencies>
Code:yii
package com.qhong; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.stereotype.Component; public class Main { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); Person person=(Person)context.getBean("babyPerson"); person.eatBreakfast(); System.out.println("==================================================="); person.eatLunch(); System.out.println("==================================================="); person.eatSupper(); System.out.println("==================================================="); person.drink("可樂"); System.out.println("==================================================="); } } interface Person { public void eatBreakfast(); public void eatLunch(); public void eatSupper(); public String drink(String name); } @Component class BabyPerson implements Person{ @Override public void eatBreakfast() { System.out.println("小Baby正在吃早餐"); } @Override public void eatLunch() { System.out.println("小Baby正在吃午飯"); } @Override public void eatSupper() { System.out.println("小Baby正在吃晚餐"); } @Override public String drink(String name) { return "小Baby在喝:"+name; } } @Component @Aspect class AdivceMethod { @Before("execution(* com.qhong.BabyPerson.*(..))") // 匹配BabyPerson類全部的方法,注意*和com之間有個空格 public void beforeEat() { System.out .println("-------------------這裏是前置加強,吃飯以前先洗小手!--------------------"); } @After("execution(* eatLunch(..))") // 匹配該工程下全部的eatLunch方法 public void afterEat() { System.out .println("-------------------這裏是後置加強,午餐吃完要睡午覺!--------------------"); } @Around("execution(* com.qhong.BabyPerson.eatSupper())") // 匹配該工程下BabyPerson的eatLunch方法 public Object aroundEat(ProceedingJoinPoint pjp) throws Throwable { System.out .println("-------------------這裏是環繞加強,吃晚飯前先玩一玩!-------------------"); Object retVal = pjp.proceed(); System.out .println("-------------------這裏是環繞加強,晚飯吃完後要得睡覺了!-------------------"); return retVal; } @AfterReturning(returning="rvt",pointcut="execution(* com.qhong.BabyPerson.drink(..))") public void log(Object rvt) { System.out .println("-------------------這裏是AfterReturning加強-------------------"); System.out.println("獲取小Baby正在喝的飲料"+rvt); System.out.println("記錄天天喝的飲料容量"); } }
beans.xmlide
<?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: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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <!-- 指定自動搜索bean組件、自動搜索切面類 --> <context:component-scan base-package="com.qhong"/> <!-- 啓動@AspectJ支持 --> <!-- proxy-target-class默認"false",更改成"ture"使用CGLib動態代理 --> <aop:aspectj-autoproxy proxy-target-class="true"/> </beans>
Result:
-------------------這裏是前置加強,吃飯以前先洗小手!-------------------- 小Baby正在吃早餐 =================================================== -------------------這裏是前置加強,吃飯以前先洗小手!-------------------- 小Baby正在吃午飯 -------------------這裏是後置加強,午餐吃完要睡午覺!-------------------- =================================================== -------------------這裏是環繞加強,吃晚飯前先玩一玩!------------------- -------------------這裏是前置加強,吃飯以前先洗小手!-------------------- 小Baby正在吃晚餐 -------------------這裏是環繞加強,晚飯吃完後要得睡覺了!------------------- =================================================== -------------------這裏是前置加強,吃飯以前先洗小手!-------------------- -------------------這裏是AfterReturning加強------------------- 獲取小Baby正在喝的飲料小Baby在喝:可樂 記錄天天喝的飲料容量 ===================================================
Spring + AspectJ(基於註解:經過 AspectJ execution 表達式攔截方法)
package com.qhong; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.stereotype.Component; public class Main { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml"); com.qhong.Greeting greeting = (com.qhong.Greeting) context.getBean("greetingImpl"); greeting.sayHello("Jack"); } } interface Greeting { void sayHello(String name); } @Component class GreetingImpl implements Greeting { @Override public void sayHello(String name) { System.out.println("Hello! " + name); } } @Aspect @Component class GreetingAspect { @Around("execution(* com.qhong.GreetingImpl.*(..))") public Object around(ProceedingJoinPoint pjp) throws Throwable { before(); Object result = pjp.proceed(); after(); return result; } private void before() { System.out.println("Before"); } private void after() { System.out.println("After"); } }
spring.xmlspa
<?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:aop="http://www.springframework.org/schema/aop" 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"> <context:component-scan base-package="com.qhong"/> <aop:aspectj-autoproxy proxy-target-class="true"/> </beans>
Result:.net
Before Hello! Jack After
遇到的bug代理
遇到這個問題應該是groupid是org.springframework的各個依賴之間版本相差太大形成的問題,全都改爲統一的就ok了。code
http://tonylit.me/2016/06/29/spring%20aop-AspectJ%E6%B3%A8%E8%A7%A3%E6%96%B9%E5%BC%8F/
http://www.yiibai.com/spring/spring-aop-aspectj-annotation-example.html
http://blog.csdn.net/xiaoxian8023/article/details/17285809
http://www.kancloud.cn/evankaka/springlearning/119670
http://git.oschina.net/lujianing/aop_demo
https://my.oschina.net/huangyong/blog/159788
https://my.oschina.net/huangyong/blog/161338
https://my.oschina.net/huangyong/blog/161402