javascript
Spring AOP 简介以及简单用法
Spring AOP 簡介以及簡單用法
如果你去面試java開發(fā), 那么Spring的AOP和DI幾乎是必問的問題。
那么AOP是什么呢?
一. AOP
所謂Aop就是 Aspect-OrientedProgramming, 中文就是面向切面編程。
我們之前聽說面向過程編程, 以及面向?qū)ο缶幊?#xff0c; 而這個面向切面編程我們可以視為是面向?qū)ο缶幊痰?個補(bǔ)充(增強(qiáng));
在一般的方法(函數(shù))中, 為了方便,可能只寫了業(yè)務(wù)代碼
1. 業(yè)務(wù)代碼
而我們我們可以將其補(bǔ)充成4個部分。
1.1 橫切關(guān)注點(diǎn) (Crosscutting Concerns)
大家看上面的方法, 就像用刀子把1個方法橫向切成4塊, 我們把上面除業(yè)務(wù)代碼外任意一個部分就叫做橫切關(guān)注點(diǎn).
1.2 切面 (Aspect)
我們可以把橫切關(guān)注點(diǎn)進(jìn)行分組, 其中任意一組就叫做切面
例如上面的例子中, 我們可以分成
1.3 通知 (Advice)
所謂通知就是切面要完成的工作。
例如對于日志通知來講, 里面執(zhí)行日志的方法我們就可以稱為1個通知。
1.4 目標(biāo) (Target)
所謂目標(biāo)就是被通知的對象, 也就是指上面例子中的原方法本身啦。
1.5 代理 (Proxy)
當(dāng)目標(biāo)被通知后產(chǎn)生的對象就叫做代理, 因?yàn)锳OP的原理就是利用代理來實(shí)現(xiàn)的, 如果想了解動態(tài)代理的可以參考這里
1.6 連接點(diǎn) (Joinpoint)
所謂Joinpoint就是程序執(zhí)行到的某個位置,
上面例子中, 業(yè)務(wù)代碼方法的執(zhí)行之前, 執(zhí)行之后, 拋出異常后 都可以視為某個連接點(diǎn)。
1.7 切點(diǎn) (PointCut)
每個方法都存在多個連接點(diǎn), 而Spring AOP利用切點(diǎn)來定位到具體那些連接點(diǎn)。
Joinpoint 和 PointCut 的關(guān)系可以作如下比喻,假如Joinpoint的數(shù)據(jù)里的記錄, 那么PointCut就相當(dāng)于查詢條件
1.8 小結(jié)
而Spring的AOP 能在不修改具體某個方法的前提下, 利用動態(tài)代理技術(shù)將通知注入到這個方法的各個連接點(diǎn)中, 令到這個方法得到了必要的補(bǔ)充。
對于上面的例子種, 我們原來的方法只有業(yè)務(wù)代碼, 但是我們可以利用Spring AOP加入 驗(yàn)證參數(shù), 日志等功能!
二. 具體例子
2.1 還沒使用AOP的例子
我們首先利用spring創(chuàng)建兩個計(jì)算類。
1個加法類, 1個減法類。
bean config 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"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd"><!-- auto scan --><context:component-scan base-package="com.home.aop"></context:component-scan> </beans>注意引入aop命名空間
計(jì)算接口 Calculator
package com.home.aop;public interface Calculator {public double getResult(double a, double b); }加法類 AddCalculator
package com.home.aop;import org.springframework.stereotype.Component;@Component public class AddCalculator implements Calculator {@Overridepublic double getResult(double a, double b) {return a + b;} }減法類 SubCalculator
package com.home.aop;import org.springframework.stereotype.Component;@Component public class SubCalculator implements Calculator {@Overridepublic double getResult(double a, double b) {return a - b;} }Client 代碼
package com.home.aop;import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;public class AopMain {public static void f(){g();}public static void g(){ApplicationContext ctx = new ClassPathXmlApplicationContext("bean-aop.xml");Calculator addCal = (Calculator) ctx.getBean("addCalculator");Calculator subCal = (Calculator) ctx.getBean("subCalculator");System.out.println(addCal.getResult(3, 1));System.out.println(subCal.getResult(3, 1));} }執(zhí)行結(jié)果
Jul 05, 2016 10:10:00 PM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@5d79a4c9: startup date [Tue Jul 05 22:10:00 CST 2016]; root of context hierarchy Jul 05, 2016 10:10:00 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions INFO: Loading XML bean definitions from class path resource [bean-aop.xml] 4.0 2.02.2 小結(jié)
上面例子中, 加法類和減法類中只包含了業(yè)務(wù)代碼, 我們可以將視為兩個Target(目標(biāo)), 下面我們就利用AOP技術(shù)為這兩個Target加入通知。
2.3 AOP 前置通知
這個任務(wù)的需求很簡單。
首先maven里要引入這些lib
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${org.springframework.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>${org.springframework.version}</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId><version>1.8.8</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.8</version></dependency>然后在bean-config xml里加入下面這個句話, enable spring aop 功能
<!-- enable @Aspect --><aop:aspectj-autoproxy></aop:aspectj-autoproxy>然后新建1個類LoggingAspect
package com.home.aop;import java.util.Arrays; import java.util.List;import org.springframework.stereotype.Component; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before;@Aspect @Component public class LoggingAspect {//@Before("execution(public double com.home.aop.AddCalculator.getResult(double,double))")@Before("execution(public * com.home.aop.*.*(..))")public void beforeExecute(JoinPoint joinPoint){String classname = joinPoint.getTarget().getClass().getSimpleName();String methodName = joinPoint.getSignature().getName();List<Object> args = Arrays.asList(joinPoint.getArgs());System.out.println("before Execute! --class name: " + classname + ", method name: " + methodName + " " + args );}}方法beforeExecute的意思就是我們要為目標(biāo)執(zhí)行之前 而注入的方法。
上面@Before 注解表示這是1個前置通知。 括號里面的就是PointCut(切點(diǎn)), 上面說過了, 相當(dāng)于數(shù)據(jù)庫里的查詢條件
然后Spring AOP 會根據(jù)PointCut 查找出所有符合條件的目標(biāo)。
內(nèi)容就很簡單了, 無非就是輸出被執(zhí)行的類名方法名和參數(shù)…
執(zhí)行結(jié)果:
Jul 06, 2016 12:30:03 AM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@6924181b: startup date [Wed Jul 06 00:30:03 CST 2016]; root of context hierarchy Jul 06, 2016 12:30:03 AM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions INFO: Loading XML bean definitions from class path resource [bean-aop.xml] before Execute! --class name: AddCalculator, method name: getResult [3.0, 1.0] 4.0 before Execute! --class name: SubCalculator, method name: getResult [3.0, 1.0] 2.0三 總結(jié)
項(xiàng)目中, 如果不用AOP 我們往往要為每個方法添加日志代碼, 十分難于維護(hù), 可讀性也大大下降, 而AOP的出現(xiàn), 就能解決這些問題。
總結(jié)
以上是生活随笔為你收集整理的Spring AOP 简介以及简单用法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring 利用FactoryBean
- 下一篇: 数据结构 - 简单选择排序法