Spring定義Bean的兩種方式:和@Bean

前言:java

Spring中最重要的概念IOC和AOP,實際圍繞的就是Bean的生成與使用。app

什麼叫作Bean呢?咱們能夠理解成對象,每個你想交給Spring去託管的對象均可以稱之爲Bean。dom

今天經過Spring官方文檔來了解下,如何生成bean,如何使用呢?測試

1.經過XML的方式來生成一個beanui

最簡單也是最原始的一種方式,經過XML來定義一個bean,咱們來看下其過程prototype

1)建立entity,命名爲Studentxml

@Data對象

@AllArgsConstructor文檔

@NoArgsConstructorget

public class Student implements Serializable {

private static final long serialVersionUID = -2088281526481179972L;

private int id;

private String name;

private int age;

}

2)在beans.xml中定義Student

<!-- 1.空值的student -->

<bean id="studentNoValue" class="domain.Student"/>

<!-- 2.帶值的student -->

<bean id="student" class="domain.Student">

<property name="id" value="11"/>

<property name="age" value="22"/>

<property name="name" value="jack"/>

</bean>

<!-- 3.全參構造:使用成員變量名稱對應 -->

<bean id="studentConstruct" class="domain.Student">

<constructor-arg name="age" value="22"></constructor-arg>

<constructor-arg name="id" value="11"></constructor-arg>

<constructor-arg name="name" value="jack"></constructor-arg>

</bean>

<!-- 4.全參構造:使用成員變量index對應 -->

<bean id="studentConstruct2" class="domain.Student">

<constructor-arg index="0" value="11"></constructor-arg>

<constructor-arg index="1" value="jack"></constructor-arg>

<constructor-arg index="2" value="22"></constructor-arg>

</bean>

<!-- 5.全參構造:使用成員變量類型對應 -->

<bean id="studentConstruct3" class="domain.Student">

<constructor-arg type="int" value="11"></constructor-arg>

<constructor-arg type="java.lang.String" value="jack"></constructor-arg>

<constructor-arg type="int" value="22"></constructor-arg>

</bean>

總結:能夠看到,建立bean的方式多種多樣,咱們能夠經過屬性來賦值<property>,也能夠經過構造參數來賦值<constructor>,關於構造賦值以上展現了三種方式,咱們能夠根據本身的需求來選擇對應的方式。

3)測試bean

public class ApplicationContextTest {

@Test

public void testXml(){

ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");

Student studentNoValue = (Student) applicationContext.getBean("studentNoValue");

Student studentFullValue = (Student) applicationContext.getBean("studentFullValue");

System.out.println(studentNoValue);

System.out.println(studentFullValue);

Student studentConstruct1 = (Student) applicationContext.getBean("studentConstruct");

Student studentConstruct2 = (Student) applicationContext.getBean("studentConstruct2");

Student studentConstruct3 = (Student) applicationContext.getBean("studentConstruct3");

System.out.println(studentConstruct1);

System.out.println(studentConstruct2);

System.out.println(studentConstruct3);

Book bookChinese = (Book) applicationContext.getBean("bookChinese");

System.out.println(bookChinese);

}

}

// res:

Student(id=0, name=null, age=0)

Student(id=11, name=jack, age=22)

Student(id=11, name=jack, age=22)

Student(id=11, name=jack, age=22)

Student(id=11, name=jack, age=22)

2.<bean>標籤深刻了解

咱們剛纔介紹了最基本的Bean使用方式,你們會發現<bean>標籤還有其餘的屬性,好比name/scope/lazy-init/init-method/...等,這些是作什麼用的呢?咱們在實際的工做中怎麼使用呢?

1)name屬性

在介紹name屬性以前,咱們先來看下ApplicationContext.getBean()的兩種方式

* ApplicationContext.getBean(String name)

* ApplicationContext.getBean(Class<T> requiredType)

第一種方式的這個name是什麼呢?咱們應該如何定義,又該如何使用呢?

// 上文示例中,咱們只是指定了Bean的id和class,以下所示

<bean id="studentNoValue" class="domain.Student" />

// 具體獲取bean的方式以下:

Student studentNoValue = (Student) applicationContext.getBean("studentNoValue");

// 能夠看到,在沒有指定bean的name屬性的時候,默認使用id來獲取bean,當作name使用

// 若是咱們不想根據id獲取,那就須要主動指定bean的name屬性,以下所示:

<bean id="studentNoValue" class="domain.Student" name="stuName"/>

// 這樣在獲取的時候,就須要使用指定的名稱來獲取,再根據id來獲取的時候就會報錯了

Student studentNoValue = (Student) applicationContext.getBean("stuName");

* 根據Class來獲取這種方式很好理解,這個不關心你定義的id或者name是什麼,使用以下:

Student studentNoValue = (Student) applicationContext.getBean(Student.class);

2)scope屬性

能夠看到,在使用scope屬性的時候,提示有兩種輸入值,分別是singleton/prototype

這個就表明了Spring-Bean的兩種建立模式,單例模式和原型模式

* Spring默認使用單例模式來建立Bean,經過ApplicationContext所得到的bean都是同一個bean(在beanName相同的狀況下),咱們能夠來驗證下

Student studentNoValue = (Student) applicationContext.getBean("stuName");

Student studentNoValue2 = (Student) applicationContext.getBean("stuName");

System.out.println(studentNoValue == studentNoValue2);// true

能夠看到的是結果輸入爲true,從工廠類中兩次獲取的stuName是同一個對象。

* 下面來驗證下原型模式

原型模式:每次獲取的bean都爲一個新的對象

// 修改beans.xml中studentNoValue的scope爲prototype

<bean id="studentNoValue" class="domain.Student" name="stuName" scope="prototype"/>

// 而後執行上面的測試代碼

Student studentNoValue = (Student) applicationContext.getBean("stuName");

Student studentNoValue2 = (Student) applicationContext.getBean("stuName");

System.out.println(studentNoValue == studentNoValue2);// false

能夠看到,輸出結果爲false,原型模式下從工廠類兩次獲取的stuName不是同一個對象。

3)init-method和destroy-method方法

見名知意,init-method應該是初始化方法的意思,destroy-method應該是銷燬方法的意思。那怎麼使用呢?

// 在Student.java中添加init()方法和destroy()方法

public void init(){

System.out.println("student init...");

}

public void destroy(){

System.out.println("student destroy...");

}

// 在beans.xml中studentNoValue的bean上添加 init-method和destroy-method

<bean id="studentNoValue" class="domain.Student" name="stuName" init-method="init" destroy-method="destroy"/>

// 測試方法以下:

ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");

Student studentNoValue = (Student) applicationContext.getBean("stuName");

applicationContext.close();

// 執行結果:

student init...

student destroy...

總結:在獲取bean的時候init()方法被執行,在容器被銷燬的時候,執行了destroy()方法

根據這個,咱們能夠在初始化bean和銷燬bean的時候作點什麼,好比關閉鏈接,保存記錄之類的操做。

延伸:那麼初始化init()方法在構造方法以前調用,仍是以後調用呢?讀者能夠自行驗證下

總結:還有一些其餘屬性,筆者就再也不一一驗證了,下面說一下經過JavaConfig的方法來實現bean的定義。

3.JavaConfig方式的bean定義

JavaConfig是Spring4.x推薦的配置方式,能夠徹底替代XML的方式定義。

1)如何定義一個Bean

// 建立一個類,命名爲SpringConfiguration

@Configuration

public class SpringConfiguration {

@Bean

public Student student(){

return new Student(11,"jack",22);

}

}

// 使用bean

AnnotationConfigApplicationContext applicationContext

= new AnnotationConfigApplicationContext(SpringConfiguration.class);

Student student = (Student) applicationContext.getBean("student")

System.out.println(student);

// res:

Student(id=11, name=jack, age=22)

相對於XML的使用方式而言,JavaConfig的使用方式基本是同步的

* @Configuration等同於<beans></beans>

* @Bean等同於<bean></bean>

* 經過AnnotationConfigApplicationContext來加載JavaConfig

* 方法名student()就等同於<bean>中的id,默認方法名就是beanName

2)@Bean的其餘參數

* name屬性等同於<bean>的name

* initMethod屬性等同於<bean>的init-method

* destroyMethod屬性等同於<bean>的destroy-method

* scope這個比較奇怪,不屬於@Bean的參數,這是一個單獨的註解,使用方式以下

@Bean(name = "stu",autowire = Autowire.BY_TYPE)

@Scope(value = "singleton")

public Student student(){

return new Student(11,"jack",22);

}

總結:

以上全文,咱們經過兩種方式來定義一個Bean,默認推薦JavaConfig。

相關文章
相關標籤/搜索