天天看點

spring基本介紹一(ioc)

一,什麼是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的使用

spring基本介紹一(ioc)
// 對目标對象建立代理對象, 使用 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(切面): 切面指的是切入點和通知的結合。

繼續閱讀