一起学习,共同进步~
文章内容
我们在之前使用过@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