FactoryBean和BeanFactory
BeanFactory 和 FactoryBean的区别?
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public interface BeanFactory { String FACTORY_BEAN_PREFIX = "&"; Object getBean(String name) throws BeansException; <T> T getBean(String name, Class<T> requiredType) throws BeansException; <T> T getBean(Class<T> requiredType) throws BeansException; Object getBean(String name, Object... args) throws BeansException; boolean containsBean(String name); boolean isSingleton(String name) throws NoSuchBeanDefinitionException; boolean isPrototype(String name) throws NoSuchBeanDefinitionException; boolean isTypeMatch(String name, Class<?> targetType) throws NoSuchBeanDefinitionException; Class<?> getType(String name) throws NoSuchBeanDefinitionException; String[] getAliases(String name); }
使用场景:
-
-
从Ioc容器中获取Bean(byName or byType)
-
检索Ioc容器中是否包含指定的Bean
-
判断Bean是否为单例
-
-
FactoryBean是个Bean,这个Bean不是简单的Bean,而是一个能生产或者修饰对象生成的工厂Bean,它的实现与设计模式中的工厂模式和修饰器模式类似。
使用场景
-
ProxyFactoryBean
-
BeanFactory和FactoryBean区别
他们两个都是 创建bean对象的
BeanFactory:提供了类似模板的方法,根据模板方法实现具体的bean创建
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
FactoryBean:则是提供了定制化的 ,独特的,与众不同的Bean创建,你可以根据自己的方式创建bean,最后通过FactoryBean中的getObject获取你定制化实现的bean
FactoryBean里面有三个方法:目的是为了做扩展,Spring Cloud 用到了FactoryBean如(FeignClientFactoryBean),feign实现了FactoryBean,getObject可以获取
当在IOC容器中的Bean实现了FactoryBean接口后,通过getBean(String BeanName)获取到的Bean对象并不是FactoryBean的实现类对象,而是这个实现类中的getObject()方法返回的对象。要想获取FactoryBean的实现类,就要getBean(&BeanName),在BeanName之前加上&。
MapperFactoryBean通过实现FactoryBean中的getObject()方法生成Mapper对应的代理对象
SqlSessionFactoryBean:创建DefaultSqlSession
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public Object getObject() { return this.getTarget(); } <T> T getTarget() { FeignContext context = (FeignContext)this.applicationContext.getBean(FeignContext.class); Builder builder = this.feign(context); if (!StringUtils.hasText(this.url)) { if (!this.name.startsWith("http")) { this.url = "http://" + this.name; } else { this.url = this.name; } this.url = this.url + this.cleanPath(); return this.loadBalance(builder, context, new HardCodedTarget(this.type, this.name, this.url)); } else { if (StringUtils.hasText(this.url) && !this.url.startsWith("http")) { this.url = "http://" + this.url; } String url = this.url + this.cleanPath(); Client client = (Client)this.getOptional(context, Client.class); if (client != null) { if (client instanceof FeignBlockingLoadBalancerClient) { client = ((FeignBlockingLoadBalancerClient)client).getDelegate(); } builder.client(client); } Targeter targeter = (Targeter)this.get(context, Targeter.class); return targeter.target(this, builder, context, new HardCodedTarget(this.type, this.name, url)); } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public T getObject() throws Exception { return this.getSqlSession().getMapper(this.mapperInterface); } //通过代理创建对象 public <T> T getMapper(Class<T> type, SqlSession sqlSession) { MybatisMapperProxyFactory<T> mapperProxyFactory = (MybatisMapperProxyFactory)this.knownMappers.get(type); if (mapperProxyFactory == null) { throw new BindingException("Type " + type + " is not known to the MybatisPlusMapperRegistry."); } else { try { return mapperProxyFactory.newInstance(sqlSession); } catch (Exception var5) { throw new BindingException("Error getting mapper instance. Cause: " + var5, var5); } } }
BeanFactory和ApplicationContext的异同
BeanFactory:
BeanFactory在启动的时候不会去实例化Bean,中有从容器中拿Bean的时候才会去实例化;
ApplicationContext:
ApplicationContext在启动的时候就把所有的Bean全部实例化了。它还可以为Bean配置lazy-init=true来让Bean延迟实例化;
应用上下文,继承BeanFactory接口,它是Spring的一各更高级的容器,提供了更多的有用的功能;
1) 国际化(MessageSource)
2) 访问资源,如URL和文件(ResourceLoader)
3) 载入多个(有继承关系)上下文 ,使得每一个上下文都专注于一个特定的层次,比如应用的web层
4) 消息发送、响应机制(ApplicationEventPublisher)
5) AOP(拦截器)
ApplicationContext:继承了bean工厂,环境,事件发布功能资源解析,获取资源等功能,功能比beanFactory更全
主要实现类:
- AnnotationConfigApplicationContext
- ClassPathXmlApplicationContext
- FileSystemXmlApplicationContext
相同:
-
Spring提供了两种不同的IOC 容器,一个是BeanFactory,另外一个是ApplicationContext,它们都是Java interface,ApplicationContext继承于BeanFactory(ApplicationContext继承ListableBeanFactory)。
-
它们都可以用来配置XML属性,也支持属性的自动注入。
-
而ListableBeanFactory继承BeanFactory),BeanFactory 和 ApplicationContext 都提供了一种方式,使用getBean("bean name")获取bean。
不同:
-
当你调用getBean()方法时,BeanFactory仅实例化bean,而ApplicationContext 在启动容器的时候实例化单例bean,不会等待调用getBean()方法时再实例化。
-
BeanFactory不支持国际化,即i18n,但ApplicationContext提供了对它的支持。
-
BeanFactory与ApplicationContext之间的另一个区别是能够将事件发布到注册为监听器的bean。
-
BeanFactory 的一个核心实现是XMLBeanFactory 而ApplicationContext 的一个核心实现是ClassPathXmlApplicationContext,Web容器的环境我们使用WebApplicationContext并且增加了getServletContext 方法。
-
如果使用自动注入并使用BeanFactory,则需要使用API注册AutoWiredBeanPostProcessor,如果使用ApplicationContext,则可以使用XML进行配置。
简而言之,BeanFactory提供基本的IOC和DI功能,而ApplicationContext提供高级功能,BeanFactory可用于测试和非生产使用,但ApplicationContext是功能更丰富的容器实现,应该优于BeanFactory