前言:     Spring中最重要的概念IOC和AOP,实际围绕的就是Bean的生成与使用。
什么叫做Bean呢?我们可以理解成对象,每一个你想交给Spring去托管的对象都可以称之为Bean。 
今天通过Spring官方文档来了解下,如何生成bean,如何使用呢? 
1.通过XML的方式来生成一个bean     最简单也是最原始的一种方式,通过XML来定义一个bean,我们来看下其过程 
1)创建entity,命名为Student 
@Data @AllArgsConstructor @NoArgsConstructor 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。  |