一,什麼是spring
spring是一款full-stack輕量級的開源架構,他是以Ioc和aop為核心。
那麼問題來了,什麼是IOC呢?
IOC稱為控制反轉,我們以前建立類的時候都是使用new的方式建立的,我們稱為主動擷取或者說控制正轉,而我們的IOC控制反轉呢,他就特殊了,是由我們的工廠建立放入容器 中,,當我們使用對象時,工廠就會提供給我們,是被動地接收的。
那麼我們來說一下什麼是工廠呢?
在這裡所說的是工廠模式,工廠模式是我們最常用的執行個體化對象模式了,是用工廠方法代替 new 操作的一種模式。工廠模式在 Java 程式系統可以說是随處可見。因為工廠模式就相當于建立執行個體對象的 new,我們經常要根據類 Class 生成執行個體對象,工廠模式也是用來建立執行個體對象的,工廠模式在後期會給你系統帶來更大的可擴充性和盡量少的修改量,提升可擴充性和可維護性。
那麼我們來說一下什麼是AOP?
面向切面程式設計。通過預編譯方式和運作期動 态代理實作程式功能的統一維護的一種技術。簡單來說,aop 是面向切面程式設計,是使用動态代理技術,實作在不修改 java 源代碼的情 況下,運作時實作方法功能的增強。減少重複代碼提高開發效率,統一管理調用,便于維護,
AOP的實作原理:在spring 中,架構會根據目标類是否實作了接口來決定采用哪種代理的方式。如果目标對象實作接口,使用的就是jdk動态代理,如果目标對象沒有實作接口那麼就是使用cglib動态代理。
問題又來了,什麼是jdk動态代理,cglib動态代理又是什麼呢?
動态代理:
代理類在程式中運作時建立的代理方式被稱為動态代理。
jdk動态代理有以下幾個特點:
代理對象,需要實作接口
代理對象的生成,是利用jdk的api,在記憶體中動态生成的對象
jdk代理類所在的包是:java.lang.reflect.Proxy,隻需要使用newProxyInstance方法,不過有三個參數
static Object newProxyInstance(ClassLoader loader, Class<?>[]
interfaces,InvocationHandler h )
注意該方法是在 Proxy 類中是靜态方法,且接收的三個參數依次為:
ClassLoader loader,:
指定目前目标對象使用類加載器,擷取加載器的方法是固定的
Class<?>[] interfaces,:
目标對象實作的接口的類型,使用泛型方式确認類型
InvocationHandler h:
事件處理,執行目标對象的方法時,會觸發事件處理器的方法,會把目前執行目标對象的
方法作為參數傳入。
示範
// 對目标對象生成代理對象
IStar proxy = (IStar)Proxy.newProxyInstance(
//1. 類加載器
App.class.getClassLoader(),
//2. 目标對象實作的接口
target.getClass().getInterfaces(),
//3. 事件處理程式
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[]
args) throws Throwable {
// 擷取方法參數
Double money = (Double) args[0];
// 判斷
if (money > 100000){
// 調用目标對象方法并傳回
return method.invoke(target,args);
} else {
System.out.println("忙,沒有檔期!!!!");
}
return null;
}
}
);
// 生成的代理對象 class com.sun.proxy.$Proxy0 implements IStar
// IStar proxy = (IStar)$Proxy0;
// LiuDeHua proxy = (LiuDeHua)$Proxy0; // 報錯:因為隻能通過接口的引用接
收具體的實作。
System.out.println(proxy.getClass());
// 調用代理方法
proxy.act(100001d);
proxy.act(1d);
Cglib代理
Cglib 代理,也叫作子類代理,它是在記憶體中動态建構一個子類對象進而實作對目标對 象功能的擴充. Cglib 是一個強大的高性能代碼生成包,它可以在運作期擴充 java 類與實作 java 接 口.它廣泛的被許多 AOP 的架構使用,例如 Spring AOP 和 synaop,為他們提供方法的 interception(攔截)
cglib的使用
// 對目标對象建立代理對象, 使用 cglib 代理
LiuDeHuaStar proxy = (LiuDeHuaStar)Enhancer.create(
LiuDeHuaStar.class,
new MethodInterceptor() {
@Override
public Object intercept(Object proxy, Method method,
Object[] args, MethodProxy methodProxy) throws Throwable {
// 擷取方法名稱
String methodName = method.getName();
// 擷取方法參數
double money = (double) args[0];
// 方法傳回值
Object reValue = null;
// 判斷
if ("singing".equals(methodName)){
// 判斷
if (money > 100000) {
// 調用唱歌方法
reValue = method.invoke(liudehua,args);
}else{
System.out.println("忙,沒空開演唱會!");
}
}
else if ("act".equals(methodName)) {
if (money > 1000000) {
// 調用目标對象
reValue = method.invoke(liudehua,args);
} else {
System.out.println("忙,不接新戲!");
}
}
return reValue;
}
});
System.out.println(proxy.getClass());
// 調用代理方法
proxy.singing(1);
proxy.act(2000000);
代理的類不能為 final,否則報錯 目标對象的方法如果為 final/static,那麼就不會被攔截,即不會執行目标對象額外 的業務方法.
AOP的專業術語
Pointcut(切入點): 所謂切入點是指我們要對哪些 Joinpoint 進行攔截的定義。
Advice(通知/增強): 所謂通知是指攔截到 Joinpoint 之後所要做的事情就是通知。 通知的類型: 前置通知,後置通知,異常通知,最終通知,環繞通知
Target(目标對象): 被代理的對象。比如動态代理案例中的演員。
Weaving(織入): 織入指的是把增強用于目标對象,建立代理對象的過程。spring 采用動态代理織入,AspectJ 采用編譯 期織入和類裝載期織入。
Proxy(代理): 一個類被 AOP 織入增強後,即産生一個結果代理類。比如動态代理案例中的經紀人。
Aspect(切面): 切面指的是切入點和通知的結合。