1. 程式人生 > 其它 >synchronized的幾種加鎖方式

synchronized的幾種加鎖方式

  控制反轉(Inversion of Control,縮寫為IoC),它是把你設計好的物件交給spring控制,而不再需要你去手動 new Object(); 網上對於IOC的解釋很多,對程式設計師而言,大篇文字的解釋,不如程式碼舉個例子:

  汽車(Car )、汽車車身 (CarBody) 、 汽車輪子(CarWheel)

  汽車 由 id + name + 車身 + 輪子 組成

  程式碼如下:

package com.wp;

public class Car {
    private int id;
    private String name;
    private CarBody carbody;
    
private CarWheel carwheel; // get set 方法省略。。。 }
package com.wp;

public class CarBody {
    private int id;
    private String name;
    //get set 方法省略。。。
}
package com.wp;

public class CarWheel {
    private int id;
    private String name;
    //get  set  方法省略。。。
}

以往的方式:我們建立汽車物件是通過直接new Car(); 的方式去出動建立物件,也就是物件的建立是有我們程式去主動控制的。程式碼如下:

package com.wp.test;
import com.wp.Car;
public class TestSpring {

    public static void main(String[] args) {
        Car car = new Car();
        System.out.println(car); //輸出 com.wp.Car@452b3a41
    }
}

在Spring中,也可以讓spring自動建立物件,程式碼如下:

首先在 applicationContext.xml 進行配置,配置class指向我們的Car 通過關鍵字c可以獲取Car物件,並且會預設給Car物件的name屬性賦值“小汽車”。

    <bean name="c" class="com.wp.Car">
        <property name="name" value="小汽車" />
    </bean>

測試類使用spring自動建立物件,程式碼如下:

package com.wp.test;
import com.wp.Car;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestSpring {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext(new String[] { "applicationContext.xml" });
        Car car = (Car) context.getBean("c");
        System.out.println(car.getName()); //輸出 小汽車
    }
}

  這種方式就是spring自動建立物件的方式,我們需要Car物件的時候,我們直接找Spring的IOC容器要就行了,我們不需要知道這個物件怎麼建立的,我們需要就直接取。

通過上面的例子來解釋一下 控制反轉:

  以往的時候,Car物件是我們程式建立,需要手動 new Car() 來建立Car物件,Car的建立是由我們控制的;

  使用Spring 的IOC原理之後,Car物件由Spring 建立,我們需要的時候,直接去取,Car的建立由Spring 控制。

  物件的建立由我們控制轉變為Spring控制,這種設計思想,就叫控制反轉

依賴注入:

什麼是依賴注入呢?簡單點,程式設計師還是通過程式的方式來理解。

可以看到我們的 CarBody 和 CarWheel 還沒派上用場,也就是我們在上面建立的小汽車的車身和輪子還都是空的,這個小汽車是無法使用的,為了讓小汽車變的完整,我們要給小汽車建立車身和輪子組裝上。還是通過以往的形式和依賴注入的形式來對比:

  以往的方式:

  我們會 new CarBody() ,然後通過Car的setCarBody() 把這物件放進去;

  然後再 new CarWheel() ,然後通過Car的setCarWheel() 把這物件放進去。
  一頓操作以後,我們的小汽車就完整了,程式碼如下:

package com.wp.test;
import com.wp.Car;
import com.wp.CarBody;
import com.wp.CarWheel;

public class Test {

    public static void main(String[] args) {
        Car car = new Car();  //建立小汽車
        CarBody carbody = new CarBody();  //建立車身 
        CarWheel carwheel = new CarWheel();  //建立輪子
car.setCarbody(carbody); //給小汽車裝上車身 car.setCarwheel(carwheel); //給小汽車裝上輪子
System.out.println(car.getCarbody());
//輸出 com.wp.CarBody@452b3a41 } }

使用Spring 的依賴注入方式:

 修改applicationContext.xml 配置檔案,通過前門spring建立小汽車物件的方式,把小汽車的車身和車輪也交給spring建立,然後通過 ref ="cb" 和 ref = "cw"的方式把車身和輪子組裝到小汽車上。注意:cb 和 cw 分別對應 車身 、輪子 bean 的name

    <bean name="c" class="com.wp.Car">
        <property name="name" value="小汽車" />
        <property name="carbody" ref="cb" />
        <property name="carwheel" ref="cw" />
    </bean>
    <bean name="cb" class="com.wp.CarBody">
        <property name="name" value="豪華車身" />
    </bean>
    <bean name="cw" class="com.wp.CarWheel">
        <property name="name" value="豪華輪子" />
    </bean>

測試類如下:

package com.wp.test;
import com.wp.Car;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestSpring {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext(new String[] { "applicationContext.xml" });
        Car car = (Car) context.getBean("c");

        System.out.println(car.getName()); //輸出 小汽車
        System.out.println(car.getCarbody().getName()); //輸出 豪華車身
        System.out.println(car.getCarwheel().getName()); //輸出 豪華輪子
    }
}

  我們已經能夠理解汽車是Spring建立的,通過context.getBean("c") 可以直接獲取汽車物件,也就是我們不需要建立物件,我們交給Spring去建立,我們需要用的時候,只管去向Spring容器要,Spring容器就會給我們一個建立好的物件。那麼Spring 是如何把“車身”和“輪子”組裝到“小汽車”上面呢,這就用到了依賴注入

  依賴注入(Dependency Injection)也是Spring框架的核心之一,縮寫 DI ,

  在applicationContext.xml 配置檔案中

    <bean name="c" class="com.wp.Car">
        <property name="name" value="小汽車" />
        <property name="carbody" ref="cb" />
        <property name="carwheel" ref="cw" />
    </bean>

  首先看下name的賦值方式,建立Car物件時,要給name 屬性賦值,賦值方式是直接指定一個value="小汽車" 也就是建立一個Car物件,直接把小汽車這個字串賦到Car物件的name屬性上,小汽車就有名字了。

  然後看下 carbody 賦值方式,賦值方式是 ref = "cb" ,spring會自動去尋找name="cb"的 bean ,而這個bean 對應的實體類就是CarBody 類 ,在找到之後,Spring會建立CarBody 物件,然後把CarBody物件賦到 Car物件的carbody 屬性上面, 小汽車就有車身了。

  CarWheel 原理與CarBody一樣。

  Car 需要CarBody ,也就是Car 依賴CarBody ,Spring這種把CarBody物件 注入到 Car 物件中的方式,就是依賴注入(DI)。

  那麼spring是如何實現依賴注入呢?

  那就是反射(reflection),<property name="carbody" ref="cb" /> 中的ref 就是反射的縮寫,這個由spring自動完成,我們不需要去進行任何操作。

使用IOC 和 DI 有什麼好處?

  以往的方式我們類裡面主動建立物件,然後處理物件與物件的依賴,會導致類與類之間高耦合,使用IOC和DI 之後呢,我們把類的控制權交給Spring,Spring去進行建立物件並且進去物件依賴注入,我們只是在需要的時候去找Spring的IOC容器去取,可以讓我們的系統結構更加靈活。

另外:

如果感覺配置檔案寫的不方便,也可以寫成註解的方式:

applicationContext.xml

<context:annotation-config/>

Car 的屬性上增加@Autowired註解
package com.wp;

import org.springframework.beans.factory.annotation.Autowired;

public class Car {
    private int id;
    private String name;
    @Autowired
    private CarBody carbody;
    @Autowired
    private CarWheel carwheel; 
  //get set 方法省略。。。 }

註解執行結果與配置檔案執行結果一致。
加油!