一起學習,共同進步~
文章內容
我們在之前使用過@ComponentScan結合@Controller、@Service、@Component、@Repository往Spring容器中註冊組件,也使用過實現ImportSelector和ImportBeanDefinitionRegistrar接口結合@Import往Spring容器中註冊組件。我們再來看一種使用FactoryBean往容器中註冊組件。
FactoryBean瞭解
先來看一下FactoryBean接口,我在下面的方法上加上註釋
<code>public interface FactoryBean{ /<code>
/**
* 返回一個由該工廠管理的的Bean實例
*/
@Nullable
T getObject() throws Exception;
/**
* 返回由該工廠管理的Bean的類型
*/
@Nullable
Class> getObjectType();
/**
* 返回該工廠管理的對象是否是單例
* 這是一個default方法,默認返回true
*/
default boolean isSingleton() {
return true;
}
}
我們來實現以下這個接口試著註冊一個Bean。
FactoryBean使用
- 我們來創建一個Grapes類,後面就將這個類註冊到Spring容器中
<code>package cn.nesive.spring.factorybean;
public class Grapes {}/<code>
- 接著我們實現FactoryBean接口,將Grapes類註冊到Spring容器中
<code>package cn.nesive.spring.factorybean;
import org.springframework.beans.factory.FactoryBean;
public class GrapesFactoryBean implements FactoryBean<grapes> {
@Override
public Grapes getObject() throws Exception {
return new Grapes();
}
@Override
public Class> getObjectType() {
return Grapes.class;
}
@Override
public boolean isSingleton() {
return true;
}
}/<grapes>/<code>
- 創建一個配置類,並通過@Import註解將GrapesFactoryBean交由Spring管理
<code>package cn.nesive.spring.factorybean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@Import(value = {GrapesFactoryBean.class})
public class FactoryBeanConfig {}/<code>
- 看看此刻Spring容器中所包含的Bean實例都有那些,我們打印一下容器中所有的Bean定義信息
<code>package cn.nesive.spring.factorybean;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class FactoryBeanTest {
@Test
public void test01(){
ApplicationContext context = new AnnotationConfigApplicationContext(
FactoryBeanConfig.class
);
String[] names = context.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
}
}/<code>
運行結果:
<code>org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
factoryBeanConfig
cn.nesive.spring.factorybean.GrapesFactoryBean/<code>
我們發現此這裡並沒有我們想要的Grapes對象,那是怎麼回事呢? 原因就是cn.nesive.spring.factorybean.GrapesFactoryBean這個名稱實際上定義的就是Grapes對象。 那我們來瞅瞅~
Bean和BeanFactoryBean
<code>package cn.nesive.spring.factorybean;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class FactoryBeanTest {
@Test
public void test01() throws Exception {
ApplicationContext context = new AnnotationConfigApplicationContext(
FactoryBeanConfig.class
);
Grapes factoryBean = (Grapes)context.getBean(
"cn.nesive.spring.factorybean.GrapesFactoryBean"
);
// 查詢cn.nesive.spring.factorybean.GrapesFactoryBean的實例類型
System.out.println(factoryBean.getClass());
// 查看是否單例
System.out.println(factoryBean == context.getBean(Grapes.class));
}
}/<code>
運行結果:
<code>class cn.nesive.spring.factorybean.Grapes
true/<code>
那麼可以我們定義名稱為cn.nesive.spring.factorybean.GrapesFactoryBean的Bean實例實際上是cn.nesive.spring.factorybean.Grapes類型。並且它是單例的。
由於我們在配置類中使用Import導入的組件是GrapesFactoryBean。那麼我們想要獲取GrapesFactoryBean實例怎麼辦呢? 答案就是需要在cn.nesive.spring.factorybean.GrapesFactoryBean之前加上"&"符號。我們來看看BeanFatory接口的FACTORY_BEAN_PREFIX註釋信息倆看看,大概意思就是:
<code>用於取消對FactoryBean實例的引用,並將其與FactoryBean創建的bean區分開來。例如,如果名為myJndiObject的bean是FactoryBean,那麼獲取&myJndiObject將返回工廠,而不是工廠返回的實例。/<code>
那我們嘗試一下在Spring容器中獲取工廠實例。
獲取FactoryBean實例
<code>package cn.nesive.spring.factorybean;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class FactoryBeanTest {
@Test
public void test01() throws Exception {
ApplicationContext context = new AnnotationConfigApplicationContext(
FactoryBeanConfig.class
);
// 加上前綴"&",獲取工廠實例
GrapesFactoryBean factoryBean = (GrapesFactoryBean)context.getBean(
"&cn.nesive.spring.factorybean.GrapesFactoryBean"
);
System.out.println(factoryBean.getClass());
}
}/<code>
來看看運行結果:
<code>class cn.nesive.spring.factorybean.GrapesFactoryBean/<code>
可以看到加上前綴"&"這個時候就返回了工廠實例。
閱讀更多 瞅瞅我頭像是啥菜 的文章
關鍵字: nesive springframework public