本文僅供學(xué)習(xí)交流使用遂庄,侵權(quán)必刪劲赠。
不作商業(yè)用途凛澎,轉(zhuǎn)載請注明出處
Spring Bean的實(shí)例化有不同方式沫换,本文將展示Spring Bean的各種實(shí)例化方式最铁。
構(gòu)造器方式
構(gòu)造器方式實(shí)例化Bean只需在Bean的Class中定義構(gòu)造器即可冷尉,然后將對應(yīng)的Bean信息注冊到容器中网严。
以下例子通過Xml配置的方式展示
- Bean的類定義
public class User {
private String name;
private Integer age;
public User() {
}
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
- Xml配置信息
<!-- 構(gòu)造器方法實(shí)例化bean配置-->
<bean id="user-by-constructor" class="com.kgyam.domain.User"/>
- 啟動(dòng)類
public class BeanInstantiationDemo {
public static void main(String[] args) {
BeanFactory beanFactory = new ClassPathXmlApplicationContext ("classpath:META-INF/bean-instantiation-context.xml");
User constructorUser = instantiationByConstructor (beanFactory);
}
static User instantiationByConstructor(BeanFactory beanFactory) {
User user = beanFactory.getBean ("user-by-constructor", User.class);
System.out.println ("instantiationByConstructor user:" + user);
return user;
}
}
靜態(tài)工廠方法
靜態(tài)工廠方法就是在剛才的User類中添加一個(gè)靜態(tài)工廠方法,然后將這個(gè)方法配置到Bean的配置信息factory-method
- User中添加一個(gè)靜態(tài)工廠方法
public class User {
private String name;
private Integer age;
public User() {
}
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public static User createUser() {
return new User();
}
}
- Xml配置信息
<!-- 靜態(tài)工廠方法實(shí)例化bean配置-->
<bean id="user-by-static-method" factory-method="createUser" class="com.kgyam.domain.User"/>
- 啟動(dòng)類
public class BeanInstantiationDemo {
public static void main(String[] args) {
BeanFactory beanFactory = new ClassPathXmlApplicationContext ("classpath:META-INF/bean-instantiation-context.xml");
User staticUser = instantiationByStaticMethod (beanFactory);
}
static User instantiationByStaticMethod(BeanFactory beanFactory) {
User user = beanFactory.getBean ("user-by-static-method", User.class);
System.out.println ("instantiationByStaticMethod user:" + user);
return user;
}
}
Factory Method
工廠方法需要定義一個(gè)能創(chuàng)建User的工廠Bean垢村,將這個(gè)工廠Bean配置到factory-bean嘉栓。
- UserFactory接口
public interface UserFactory {
User createUser();
}
- UserFactory的默認(rèn)實(shí)現(xiàn)
/**
* User實(shí)例工廠
*/
public class DefaultUserFactory implements UserFactory {
@Override
public User createUser() {
return User.createUser();
}
}
- Xml配置
<bean id="user-by-factory-method" factory-bean="user-factory" class="com.kgyam.domain.User"></bean>
<!-- 工廠方法的工廠bean配置-->
<bean id="user-factory" class="com.kgyam.factory.DefaultUserFactory"/>
- 啟動(dòng)類跟上面的是一樣的侵佃,只是getBean的BeanName改下就好
FactoryBean
需要實(shí)現(xiàn)FactoryBean接口馋辈,并將實(shí)現(xiàn)類注冊到容器中
- FactoryBean的實(shí)現(xiàn)類
/**
* User的FactoryBean
*/
public class UserFactoryBean implements FactoryBean {
@Override
public Object getObject() throws Exception {
return new User ();
}
@Override
public Class<?> getObjectType() {
return User.class;
}
}
- Xml配置
<!-- 通過factoryBean實(shí)例化user的factoryBean配置 -->
<bean id="user-factory-bean" class="com.kgyam.domain.UserFactoryBean" />
- 啟動(dòng)類這里迈螟,雖然bean定義的class是UserFactoryBean,但是接收返回的類型還是使用User褥民,beanName改成對應(yīng)Xml配置定義的消返。獲取Bean的方法如下
static User instantiationByFactroyBean(BeanFactory beanFactory) {
User user = beanFactory.getBean ("user-factory-bean", User.class);
System.out.println ("instantiationByFactroyBean user:" + user);
return user;
}
ServiceLoaderFactoryBean
通過ServiceLoaderFactoryBean的這種方式實(shí)例化Bean利用的是SPI機(jī)制實(shí)現(xiàn)的耘拇。
- 接口類
public interface UserService {
User createUser();
}
- 接口實(shí)現(xiàn)類
這里定義兩個(gè)接口實(shí)現(xiàn)類
public class DefaultUserServiceImpl implements UserService {
@Override
public User createUser() {
User user = User.createUser();
user.setName("defaultUser");
return user;
}
}
public class CustomUserServiceImpl implements UserService {
@Override
public User createUser() {
User user = User.createUser();
user.setName("customUser");
return user;
}
}
- META-INF下services配置
這里注意的是配置文件名稱需要時(shí)接口的限定類名,配置文件中配置的是實(shí)現(xiàn)類的限定類名秦驯。這里屬于SPI的知識译隘,不過多闡述
com.kgyam.domain.service.DefaultUserServiceImpl
com.kgyam.domain.service.CustomUserServiceImpl
- Xml配置
注意這里的class配置的是ServiceLoaderFactoryBean
<bean id="service-loader-factory-bean" class="org.springframework.beans.factory.serviceloader.ServiceLoaderFactoryBean">
<property name="serviceType" value="com.kgyam.domain.service.UserService"/>
</bean>
- 啟動(dòng)類
public class BeanInstantiationDemo {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:META-INF/bean-instantiation-special-context.xml");
instantiationByServiceLoader(applicationContext);
}
}
/**
* 通過ServiceLoaderFactoryBean方式實(shí)例化bean
* <p>
* 使用SPI的方式還是需要遵循SPI原來的規(guī)范,META-INF下設(shè)定好services的文件
* 否則會(huì)無法找到這些實(shí)現(xiàn)類厅目。
*
* @param beanFactory
*/
static void instantiationByServiceLoader(BeanFactory beanFactory) {
ServiceLoader<UserService> services = beanFactory.getBean("service-loader-factory-bean", ServiceLoader.class);
Iterator<UserService> iterator = services.iterator();
while (iterator.hasNext()) {
User user = iterator.next().createUser();
System.out.println(user);
}
}
BeanDefinitionRegistry
通過BeanDefinitionRegistry注冊BeanDefinition實(shí)現(xiàn)Bean實(shí)例化
- 啟動(dòng)類
這里AnnotationConfigApplicationContext實(shí)現(xiàn)了BeanDefinitionRegistry,
所以通過上下文對象注冊即可法严。
public class BeanInstantiationDemo {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext ();
applicationContext.register (BeanInstantiationSpecialDemo.class);
BeanDefinitionBuilder beanDefinitionBuilder = genericBeanDefinition (User.class);
beanDefinitionBuilder.addPropertyValue ("name", "dali");
/*
因?yàn)锳nnotationConfigApplicationContext實(shí)現(xiàn)了BeanDefinitionRegistry接口,所以可以直接調(diào)用
*/
applicationContext.registerBeanDefinition ("dali-user", beanDefinitionBuilder.getBeanDefinition ());
applicationContext.refresh ();
User user = applicationContext.getBean ("dali-user", User.class);
System.out.println ("BeanDefinitionRegistry#registerBeanDefinition(String,Object):" + user);
applicationContext.close ();
}
}