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。

相关文章
相关标签/搜索