spring创建bean的四种常用实例
- 通过反射调用构造方法创建bean对象
- 通过静态工厂方法创建bean对象
- 通过实例工厂方法创建bean对象
- 通过FactoryBean创建bean对象
通过反射调用构造方法创建bean对象
调用类的构造方法获取对应的bean实例,是使用最多的方式,这种方式只需要在xml bean元素中指定class属性,spring容器内部会自动调用该类型的构造方法来创建bean对象,将其放在容器中以供使用。
语法
<bean id="bean名称" name="bean名称或者别名" class="bean的完整类型名称">
<constructor-arg index="0" value="bean的值" ref="引用的bean名称" />
<constructor-arg index="1" value="bean的值" ref="引用的bean名称" />
<constructor-arg index="2" value="bean的值" ref="引用的bean名称" />
....
<constructor-arg index="n" value="bean的值" ref="引用的bean名称" />
</bean>
constructor-arg用于指定构造方法参数的值
index:构造方法中参数的位置,从0开始,依次递增
value:指定参数的值
ref:当插入的值为容器内其他bean的时候,这个值为容器中对应bean的名称
案例
@Getter
@Setter
@ToString
public class UserModel {
private String name;
private int age;
public UserModel() {
this.name = "我是通过UserModel的无参构造方法创建的!";
}
public UserModel(String name, int age) {
this.name = name;
this.age = age;
}
}
beans.xml配置
<!-- 通过UserModel的默认构造方法创建UserModel对象 -->
<bean id="createBeanByConstructor1" class="com.javacode2018.lesson001.demo3.UserModel"/>
<!-- 通过UserModel有参构造方法创建UserModel对象 -->
<bean id="createBeanByConstructor2" class="com.javacode2018.lesson001.demo3.UserModel">
<constructor-arg index="0" value="我是通过UserModel的有参方法构造的对象!"/>
<constructor-arg index="1" value="30"/>
</bean>
上面这2种写法,spring容器创建这两个UserModel的时候,都会通过反射的方式去调用UserModel类中对应的构造函数来创建UserModel对象。
测试
以下测试类,同理
public static void main(String[] args) {
//1.bean配置文件位置
String beanXml = "classpath:/com/javacode2018/lesson001/demo3/beans.xml";
//2.创建ClassPathXmlApplicationContext容器,给容器指定需要加载的bean配置文件
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(beanXml);
System.out.println("spring容器中所有bean如下:");
//getBeanDefinitionNames用于获取容器中所有bean的名称
for (String beanName : context.getBeanDefinitionNames()) {
System.out.println(beanName + ":" + context.getBean(beanName));
}
}
通过静态工厂方法创建bean对象
我们可以创建静态工厂,内部提供一些静态方法来生成所需要的对象,将这些静态方法创建的对象交给spring以供使用
<bean id="bean名称" name="" class="静态工厂完整类名" factory-method="静态工厂的方法">
<constructor-arg index="0" value="bean的值" ref="引用的bean名称" />
<constructor-arg index="1" value="bean的值" ref="引用的bean名称" />
<constructor-arg index="2" value="bean的值" ref="引用的bean名称" />
....
<constructor-arg index="n" value="bean的值" ref="引用的bean名称" />
</bean>
class:指定静态工厂完整的类名
factory-method:静态工厂中的静态方法,返回需要的对象。
constructor-arg用于指定静态方法参数的值,用法和上面介绍的构造方法一样。
案例
public class UserStaticFactory {
/**
* 静态无参方法创建UserModel
*
* @return
*/
public static UserModel buildUser1() {
System.out.println(UserStaticFactory.class + ".buildUser1()");
UserModel userModel = new UserModel();
userModel.setName("我是无参静态构造方法创建的!");
return userModel;
}
/**
* 静态有参方法创建UserModel
*
* @param name 名称
* @param age 年龄
* @return
*/
public static UserModel buildUser2(String name, int age) {
System.out.println(UserStaticFactory.class + ".buildUser2()");
UserModel userModel = new UserModel();
userModel.setName(name);
userModel.setAge(age);
return userModel;
}
}
<!-- 通过工厂静态无参方法创建bean对象 -->
<bean id="createBeanByStaticFactoryMethod1" class="com.javacode2018.lesson001.demo3.UserStaticFactory"
factory-method="buildUser1"/>
<!-- 通过工厂静态有参方法创建bean对象 -->
<bean id="createBeanByStaticFactoryMethod2" class="com.javacode2018.lesson001.demo3.UserStaticFactory"
factory-method="buildUser2">
<constructor-arg index="0" value="通过工厂静态有参方法创建UerModel实例对象"/>
<constructor-arg index="1" value="30"/>
</bean>
通过实例工厂方法创建bean对象
让spring容器去调用某些对象的某些实例方法来生成bean对象放在容器中以供使用
<bean id="bean名称" factory-bean="需要调用的实例对象bean名称" factory-method="bean对象中的方法">
<constructor-arg index="0" value="bean的值" ref="引用的bean名称" />
<constructor-arg index="1" value="bean的值" ref="引用的bean名称" />
<constructor-arg index="2" value="bean的值" ref="引用的bean名称" />
....
<constructor-arg index="n" value="bean的值" ref="引用的bean名称" />
</bean>
spring容器以factory-bean的值为bean名称查找对应的bean对象,然后调用该对象中factory-method属性值指定的方法,将这个方法返回的对象作为当前bean对象放在容器中供使用。
案例
定义一个实例工厂
public class UserFactory {
public UserModel buildUser1() {
System.out.println("----------------------1");
UserModel userModel = new UserModel();
userModel.setName("bean实例方法创建的对象!");
return userModel;
}
public UserModel buildUser2(String name, int age) {
System.out.println("----------------------2");
UserModel userModel = new UserModel();
userModel.setName(name);
userModel.setAge(age);
return userModel;
}
}
<!-- 定义一个工厂实例 -->
<bean id="userFactory" class="com.javacode2018.lesson001.demo3.UserFactory"/>
<!-- 通过userFactory实例的无参user方法创建UserModel对象 -->
<bean id="createBeanByBeanMethod1" factory-bean="userFactory" factory-method="buildUser1"/>
<!-- 通过userFactory实例的有参user方法创建UserModel对象 -->
<bean id="createBeanByBeanMethod2" factory-bean="userFactory" factory-method="buildUser2">
<constructor-arg index="0" value="通过bean实例有参方法创建UserModel实例对象"/>
<constructor-arg index="1" value="30"/>
</bean>
通过FactoryBean来创建bean对象
前面我们学过了BeanFactory接口,BeanFactory是spring容器的顶层接口,而这里要说的是FactoryBean,也是一个接口,这两个接口很容易搞混淆,FactoryBean可以让spring容器通过这个接口的实现来创建我们需要的bean对象。
public interface FactoryBean<T> {
/**
* 返回创建好的对象
*/
@Nullable
T getObject() throws Exception;
/**
* 返回需要创建的对象的类型
*/
@Nullable
Class<?> getObjectType();
/**
* bean是否是单例的
**/
default boolean isSingleton() {
return true;
}
}
接口中有3个方法,前面2个方法需要我们去实现,getObject方法内部由开发者自己去实现对象的创建,然后将创建好的对象返回给Spring容器,getObjectType需要指定我们创建的bean的类型;最后一个方法isSingleton表示通过这个接口创建的对象是否是单例的,如果返回false,那么每次从容器中获取对象的时候都会调用这个接口的getObject() 去生成bean对象。
<bean id="bean名称" class="FactoryBean接口实现类" />
package com.javacode2018.lesson001.demo3;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.lang.Nullable;
/**
* 公众号:路人甲Java,工作10年的前阿里P7分享Java、算法、数据库方面的技术干货!坚信用技术改变命运,让家人过上更体面的生活!
*/
public class UserFactoryBean implements FactoryBean<UserModel> {
int count = 1;
@Nullable
@Override
public UserModel getObject() throws Exception { //@1
UserModel userModel = new UserModel();
userModel.setName("我是通过FactoryBean创建的第"+count+++ "对象");//@4
return userModel;
}
@Nullable
@Override
public Class<?> getObjectType() {
return UserModel.class; //@2
}
@Override
public boolean isSingleton() {
return true; //@3
}
}
@1:返回了一个创建好的UserModel对象
@2:返回对象的Class对象
@3:返回true,表示创建的对象是单例的,那么我们每次从容器中获取这个对象的时候都是同一个对象,false的话,每次会创建
<!-- 通过FactoryBean 创建UserModel对象 -->
<bean id="createByFactoryBean" class="com.javacode2018.lesson001.demo3.UserFactoryBean"/>
转载
https://blog.csdn.net/likun557/article/details/104284840