1. 程式人生 > >Spring AOP的底層實現原理

Spring AOP的底層實現原理

Spring的兩大核心之一就是AOP,AOP:面向切面程式設計。在說原理之前,得先知道一些AOP的專業術語。

AOP的專業術語

連線點(JoinPoint):增強執行的位置(增加程式碼的位置),Spring只支援方法;

切點(PointCut):具體的連線點;一般可能通過一個表示式來描述;

增強(Advice):也稱為訊息,指的是增加的額外的程式碼,Spring中,增強除了包含程式碼外,還包含位置資訊;

Spring中一共有四種增強:

MethodBeforeAdvice:前置增強

MethodInterceptor:環繞增強

ThrowsAdvice:異常增強

AfterReturingAdvice

:返回值增強

引介(Introduction):特殊的增強,動態為類增加方法

織入(Weaving):將增強加入到目標類的過程,織入分為三種時期

編譯器:AspectJ

類載入

執行期:jdk動態代理(實現介面),CGlib(子類,不能用final

目標物件(Target):原始物件

代理物件(Proxy):加入了增強的物件,是生成的;

切面(Aspect):切點+增強

接下來我要說的就是在執行期間織入的兩種實現方式

JDK動態代理(實現介面)

什麼是代理模式呢?

  代理模式有三個角色,分別是

抽象角色:介面

目標角色:實現類

代理角色:實現介面(InvocationHandler),並引用目標角色

代理模式與裝飾者模式的區別

類圖(結構)基本一樣,但目的不同,裝飾模式的前提是已經所有的類,並進行組裝;而

使用代理模式時,我們不能直接訪問目標角色或沒有許可權訪問時,可以使用代理模式

代理模式分為兩種

靜態代理:需要為每個目標角色,建立一個對應的代理角色;類的數量會急劇膨脹

動態代理:自動為每個目標角色生成對應的代理角色

接下來就是jdk動態代理的程式碼:

實現jdk動態代理的前提是所有的目標類都必須要基於一個統一的介面

建立統一的介面

package com.dao;


/**
 * 為目標類定義統一的介面SleepDao
 * @author XuXQ
 *
 */
public interface SleepDao {

public void sleep();


}

定義目標物件
package com.daoImpl;

import com.dao.SleepDao;

/**
 * 目標類
 * @author XuXQ
 *
 */
public class SleepDaoImpl implements SleepDao {

	@Override
	public void sleep() {
		System.out.println("本大人要睡覺了");
	}

}

建立代理角色

package com.handler;


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
 * 建立的類得需要實現InvocationHandler,並重寫invoke()方法
 * InvocationHandler 是代理例項的呼叫處理程式 實現的介面
 * 即:MyInvocationHandler 是代理例項的呼叫處理程式
 * @author XuXQ
 *
 */
public class MyInvoctionHandler implements InvocationHandler {
	Object object=null;//目標物件
	


	public MyInvoctionHandler(Object object) {
		super();
		this.object = object;
	}




	/**
	 * proxy=代理物件
	 * method=被呼叫方法的方法名
	 * args=被呼叫方法的引數
	 */
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println("睡覺前要脫衣服啊");
		Object obj=method.invoke(object, args);//obj為目標物件呼叫方法的返回值
		System.out.println("睡著了當然得做個美夢啊");
		return obj;
	}


}


編寫測試用例
package com.handler;

import static org.junit.Assert.*;

import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.dao.SleepDao;
import com.daoImpl.SleepDaoImpl;

public class Test1 {

	@Before
	public void setUp() throws Exception {
	}

	@After
	public void tearDown() throws Exception {
	}

	@Test
	public void test() {
		//目標類必須基於統一的介面
		SleepDao s=new SleepDaoImpl();
		ClassLoader classLoader=s.getClass().getClassLoader();
		MyInvoctionHandler myInvoctionHandler=new MyInvoctionHandler(s);
		
		//Proxy為InvocationHandler實現類動態建立一個符合某一介面的代理例項  
		SleepDao sd=(SleepDao) Proxy.newProxyInstance(classLoader, s.getClass().getInterfaces(), myInvoctionHandler);
		
		//相當於呼叫代理角色的Invoke()
		sd.sleep();
	}

}

結果:


由結果可以看到成功的將增強織入到了目標物件中了

CGlib代理

package com.cglibproxy;
/**
 * 和JDK動態代理不同,不需要建立統一的介面
 * @author XuXQ
 *
 */
public class Base {
	public void sleep(){
		System.out.println("本大少要睡覺啦");
	}
}
建立cglib的代理物件
package com.cglibproxy;

import java.lang.reflect.Method;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;


//用來生成代理物件
public class CglibProxy implements MethodInterceptor {
	
	public Object getProxy(Object object){
		Enhancer e=new Enhancer();//建立代理物件類
		e.setSuperclass(object.getClass());//宣告代理物件的父類是誰(是目標物件)
		e.setCallback(this);//設定回撥函式,即呼叫intercept()
		return e.create();//返回建立的代理物件
	}
	/**
 * proxy=代理物件,也是目標物件的子類
 * args=方法引數
 */
	@Override
	public Object intercept(Object proxy, Method method, Object[] args, MethodProxy arg3) throws Throwable {
		System.out.println("你個大懶豬,竟然睡覺前不脫衣服,嫌棄o");
		Object object=arg3.invokeSuper(proxy, args);
		System.out.println("起床啦,要不然得遲到了哦");
		return null;
	}

}

編寫測試用例
package com.cglibproxy;

import static org.junit.Assert.*;

import org.junit.After;
import org.junit.Before;

public class Test {

	@Before
	public void setUp() throws Exception {
	}

	@After
	public void tearDown() throws Exception {
	}

	@org.junit.Test
	public void test() {
		CglibProxy proxy=new CglibProxy();
		Base base=(Base) proxy.getProxy(new Base());
		base.sleep();
	}

}

結果:


由結果同樣可以看到成功的將增強織入到了目標物件中了

總結

當然我們以後寫程式碼都是基於Aspect,直接寫註解的,當然這並不代表這我們不需要知道AOP

底層的實現原理,至於註解用的是哪種實現方式,使用配置來解決的,這裡就不詳解了。

相關推薦

Spring AOP底層實現原理

1、spring的AOP底層是由 JDK提供的動態代理技術 和 CGLIB(動態位元組碼增強技術)實現。 2、JDK動態代理:Jdk動態代理只針對於介面操作。 3、CGLIB:可以針

Spring技術內幕:Spring AOP實現原理(三)

dede ide configure ida mini == src min dem 生成SingleTon代理對象在getSingleTonInstance方法中完畢,這種方法時ProxyFactoryBean生成AopProxy對象的入口。代理對象會

AOP底層實現原理,動態代理如何動態

需求 原理 靜態代理 朋友 hand 自己 依賴 開發 ava 代理 指定另外一個主體代替原來的某個主體去執行某個事物 代理執行的人 需要代理的人 需要代理的事情是一定要做的 但是被代理的人沒有時間或自己做的不專業 靜態代理: 父母朋友幫忙物色找對象 代理人掌握需求,專

Spring AOP實現原理

class文件 ndb 是我 反射 ofo 直接 pri 關註 選擇 AOP(Aspect Orient Programming),我們一般稱為面向方面(切面)編程,作為面向對象的一種補充,用於處理系統中分布於各個模塊的橫切關註點,比如事務管理、日誌、緩存等等。AOP實現的

Spring AOP實現原理

代碼生成 time .get hand 日誌 aop 分布 class a cee AOP(Aspect Orient Programming),我們一般稱為面向方面(切面)編程,作為面向對象的一種補充,用於處理系統中分布於各個模塊的橫切關註點,比如事務管理、日誌、緩存等等

springSpring aop實現原理

本文轉載自https://www.cnblogs.com/lcngu/p/5339555.html。 Spring aop的實現原理 簡介   前段時間寫的java設計模式--代理模式,最近在看Spring Aop的時候,覺得於代理模式應該有密切的聯絡,於是決定了解下Sprin

深入理解spring事務底層實現原理

事務 相信大家都在ATM機取過錢,但是是否有人考慮過它的流程是怎樣的呢? 我們都知道,假如我們取300塊錢,那麼當這三百塊錢從ATM機出來時,我們的賬戶相應的會減少300。這兩個過程一定是要同時成功才算成功的。否則就會出現賬戶少了300.但是錢沒出來,對於我們來

反射實現 AOP 動態代理模式例項說明(Spring AOP實現 原理)

說明以下,spring aop的實現原理不是用java的動態代理。是用代理模式和CGLib (Code GenerationLibrary), 不過現在不用CGLib(Code Generation Library),直接用ASM框架來操作位元組碼了。 好長時間沒有用過S

Spring Aop 原始碼實現原理分析

更新:2018/4/2 修改字型、新增引言。0   引言AOP是Aspect Oriented Programing的簡稱,面向切面程式設計。AOP適合於那些具有橫切邏輯的應用:如效能監測,訪問控制,事務管理、快取、物件池管理以及日誌記錄。AOP將這些分散在各個業務邏輯中的程

Spring AOP IOC 實現原理,面試問到如何回答

IOC:控制反轉也叫依賴注入,IOC利用java反射機制,AOP利用代理模式。所謂控制反轉是指,本來被呼叫者的例項是有呼叫者來建立的,這樣的缺點是耦合性太強,IOC則是統一交給spring來管理建立,將物件交給容器管理,你只需要在spring配置檔案總配置相應的

Spring AOP底層實現- JDK動態代理和CGLIB動態代理

Spring AOP是執行時織入的,那麼執行時織入到底是怎麼實現的呢?答案就是代理物件。 代理又可以分為靜態代理和動態代理。 靜態代理:由程式設計師建立或特定工具自動生成原始碼,再對其編譯。在程式執行前,代理類的.class檔案就已經存在了。

Spring AOP實現原理—— 靜態代理和動態代理

AOP(Aspect Orient Programming),我們一般稱為面向方面(切面)程式設計,作為面向物件的一種補充,用於處理系統中分佈於各個模組的橫切關注點,比如事務管理、日誌、快取等等。 AOP實現的關鍵在於AOP框架自動建立的AOP代理,

Spring IOC和Spring AOP實現原理(原始碼主線流程)

寫在前面      正本文參考了《spring技術內幕》和spring 4.0.5原始碼。本文只描述原理流程的主線部分,其他比如驗證,快取什麼可以具體參考原始碼理解。Spring IOC一、容器初始化      容器的初始化首先是在對應的構造器中進行,在application

Spring AOP實現原理(二)

**二、AOP的設計與實現 1、JVM的動態代理特性** 在Spring AOP實現中, 使用的核心技術時動態代理,而這種動態代理實際上是JDK的一個特性。通過JDK的動態代理特性,可以為任意Java物件建立代理物件,對於具體使用來說,這個特性使通過Java Reflectio

反射實現 AOP 動態代理模式(Spring AOP實現 原理)

{40            //反射得到操作者的例項41            Class clazz = this.proxy.getClass();42            //反射得到操作者的Start方法43            Method start = clazz.getDeclaredM

Spring Aop底層原理詳解(利用spring後置處理器實現AOP

寫在前面:對於一個java程式設計師來說,相信絕大多數都有這樣的面試經歷,面試官問:你知道什麼是aop嗎?談談你是怎麼理解aop的?等等諸如此類關於aop的問題。當然對於一些小白可能會一臉懵逼;對於一些工作一兩年的,可能知道,哦!aop就是面向切面變成,列印日誌啊,什麼什麼的,要是有點學

探析Spring AOP(三):Spring AOP底層實現原理

一、前言   前面第一篇我們講到了AOP的概念和使用,第二篇也講到了 AOP的實現機制,在第一篇,講到了joinpoint,pointcut,aspect,weave等AOP的核心概念,接下來我們詳解分析他們的實現原理!   在動態代理 和 CGLIB 的支

Spring AOP底層實現原理

Spring的兩大核心之一就是AOP,AOP:面向切面程式設計。在說原理之前,得先知道一些AOP的專業術語。 AOP的專業術語 連線點(JoinPoint):增強執行的位置(增加程式碼的位置),Spring只支援方法; 切點(PointCut):具體的連線點;一般可能通過

菜鳥學SSH——Spring容器AOP實現原理——動態代理

之前寫了一篇關於IOC的部落格——《Spring容器IOC解析及簡單實現》,今天再來聊聊AOP。大家都知道Spring的兩大特性是IOC和AOP。 IOC負責將物件動態的注入到容器,從而達到一種需要誰就注入誰,什麼時候需要就什麼時候注入的效果,可謂是招之則來,揮之則去。想想都覺得爽,如果現實

Spring】:aop實現原理

銜接前篇文章:https://blog.csdn.net/hxcaifly/article/details/85061330 前言 前段時間寫的java設計模式–代理模式,最近在看Spring Aop的時候,覺得於代理模式應該有密切的聯絡,於是決定了解下Spring A