AOP
AOP
AOP簡介
什么是AOP?
AOP為Aspect Oriented Programming的縮寫,意為:面向切面編程,通過預編譯方式和運行期間動態代理實現程序功能的統一維護的一種技術。利用AOP可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度降低,提高程序的可重用性,同時提高了開發的效率。
AOP的作用及其優勢
- 作用:在程序運行期間,在不修改源碼的情況下對方法進行功能增強
- 優勢:減少重復代碼,提高開發效率,并且便于維護
AOP的底層實現
實際上AOP的底層通過Spring的動態代理技術實現的。在運行期間,spring通過動態代理技術動態生成代理對象,代理方法執行時進行增強功能的介入,在去調用目標對象的方法,從而完成功能的增強

JDK的動態代理
public class Test {
public static void main(String[] args) {
// target是目標對象類
final Target target = new Target();
// 獲得增強對象--advice是增強類
final Advice advice = new Advice();
// 返回值是動態生成的代理對象
TargetInterface proxy = (TargetInterface) Proxy.newProxyInstance(
target.getClass().getClassLoader(), //目標對象類加載器
target.getClass().getInterfaces(), //目標對象相同的接口組件名對象數組
new InvocationHandler() {
//調用代理對象的任何方法,實質執行的都是這個invoke方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 前置增強
advice.before();
// 執行目標方法
Object invoke = method.invoke(target, args);
// 后置增強
advice.after();
return invoke;
}
}
);
// 調用代理對象的方法
proxy.save();
}
}
cglib的動態代理
導入了spring-context就可以用了
public class Test {
public static void main(final String[] args) {
final Target target = new Target();
// 獲得增強對象
final Advice advice = new Advice();
// 返回值是動態生成的代理對象
// 需要參加增強器
Enhancer enhancer = new Enhancer();
// 設置父類(目標)
enhancer.setSuperclass(Target.class);
// 設置回調
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
// 執行前置
advice.before();
// 執行目標
Object invoke = method.invoke(target, args);
// 執行后置
advice.after();
return invoke;
}
});
// 創建代理對象
Target proxy = (Target) enhancer.create();
proxy.save();
}
AOP的相關概念
- Target(目標對象):代理的目標對象(需要增強的目標方法)
- Proxy(代理):一個類被AOP加入增強后,就產生一個結果代理類‘
- Joinpoint(連接點):被攔截的點(sping只支持方法類型的連接點 ),可以被增強的方法
- PointCut(切入點):我們進行攔截的那一部分的Joinpoint,被增強的連接點
- Advice(通知/增強):攔截到joinpoint之后要做的事情
- Aspect(切面):切入點和通知的結合
- Weaving(織入):把增強應用到目標對象來創建新的代理對象的過程。spring采用動態代理織入
AOP開發明確的事項
-
需要編寫的內容
- 核心業務代碼(目標類的目標方法)
- 編寫切面類,切面類中有通知
- 在配置文件中,配置織入關系,即將哪些通知與哪些連接點進行結合
-
AOP技術實現的內容
![]()
![]()
AOP的實現
基于xml的AOP實現
快速入門
-
導入AOP坐標(常量sping-context外)
<!-- aspectj框架--> <dependency> <groupId>org.apache.geronimo.bundles</groupId> <artifactId>aspectjweaver</artifactId> <version>1.6.8_2</version> </dependency> -
創建目標接口和目標類(內部有切點)
![]()
-
創建切面類(內部有增強方法)
![]()
-
將目標類和切面類的對象創建權交給spring
在spring的配置文件中:
<!-- 目標對象--> <bean id="target" class="com.myspring.JDK.Target"></bean> <!-- 切面對象--> <bean id="myAspect" class="com.myspring.JDK.MyAspect"></bean> -
在applicationContext.xml中配置織入關系
<!-- 配置織入,告訴spring框架 哪些方法需要進行哪些增強--> <aop:config> <!-- 聲明切面--> <aop:aspect ref="myAspect"> <!-- 切面:切點+通知--> <!-- 指定前置增強方法,和指定增強的切點--> <aop:before method="before" pointcut="execution(public void com.myspring.JDK.Target.save())"></aop:before> </aop:aspect> </aop:config> -
測試:用了spring-test
package com.myspring.JDK; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class test { @Autowired private TargetInterface target; @Test public void test1(){ target.save(); } }
配置切面表達式的寫法

配置通知的類型

環繞方法:

切點表達式的抽取:

基于注解的AOP開發
快速入門
-
創建目標接口和目標類(內部有切點)
-
創建切面類(內部有增強方法)
上面兩步和前面寫的類似
-
將目標類和切面類的對象創建權交給spring
@Component("myAspect") @Component("aspect") //在兩個類分別加入這兩者的注解例如:
@Component("target") public class Target implements TargetInterface { public void save(){ System.out.println("hello world"); } } -
在切面類中使用注解配置織入關系
@Aspect//標注當前MyAspect是一個切面類@Component("myAspect") @Aspect//標注當前MyAspect是一個切面類 public class MyAspect { // 前置增強和增強的切點 @Before(value = "execution(* com.myspring.JDK.Target.save())") public void before(){ System.out.println("前置增強"); } } -
在配置文件中開啟組件掃描和AOP自動代理
applicationContext-anno.xml:
<!-- 組件掃描--> <context:component-scan base-package="com.myspring.JDK"/> <!-- aop自動代理--> <aop:aspectj-autoproxy/> -
測試
注解配置詳解
通知類型:

切點表達式的抽取:
@Component("myAspect")
@Aspect//標注當前MyAspect是一個切面類
public class MyAspect {
// 前置增強和增強的切點
@Before(value = "pointCut()")
public void before(){
System.out.println("前置增強");
}
@After("MyAspect.pointCut()")
public void after(){
System.out.println("后置增強");
}
// 定義切點表達式
@Pointcut("execution(* com.myspring.JDK.Target.save())")
public void pointCut(){}
}




浙公網安備 33010602011771號