beanFactory 、ApplicationContext、FactoryBean、
BeanFactory
BeanFactory 是 Spring 的“心脏”。就是 Spring IoC 容器的真面目。Spring 使用 BeanFactory 来实例化、配置和管理 Bean。
BeanFactory:是IOC容器的核心接口, 定义IOC的基本功能,主要定义getBean方法。getBean方法是IOC容器获取bean对象和引发依赖注入的起点。方法的功能是返回特定的名称的Bean。
BeanFactory 是初始化 Bean 和调用它们生命周期方法的“吃苦耐劳者”。注意,BeanFactory 只能管理单例(Singleton)Bean 的生命周期。不能管理原型(prototype,非单例)Bean 的生命周期。因为原型 Bean 实例被创建之后便被传给客户端,容器失去了对它们的引用。

BeanFactory作为最顶层的一个接口类,定义IOC容器的基本功能规范,BeanFactory 有三个子类:ListableBeanFactory、HierarchicalBeanFactory 和AutowireCapableBeanFactory。最终的默认实现类是 DefaultListableBeanFactory,实现了所有的接口。那为何要定义这么多层次的接口呢?主要是为了区分在 Spring 内部在操作过程中对象的传递和转化过程中,对对象的数据访问所做的限制。例如:
- ListableBeanFactory 接口:表示 Bean 是可列表的。
- HierarchicalBeanFactory 接口:表示的是这Bean 是有继承关系的,也就是每个Bean 有可能有父 Bean。
- AutowireCapableBeanFactory 接口:定义 Bean 的自动装配规则。
看一下BeanFactory的源码:
package org.springframework.beans.factory; public interface BeanFactory { /** * 用来引用一个实例,或把它和工厂产生的Bean区分开,如果一个FactoryBean的名字为a,那么,&a会得到那个Factory */ String FACTORY_BEAN_PREFIX = "&"; /* * 四个不同形式的getBean方法,获取实例 */ Object getBean(String name) throws BeansException;
//返回给定名称注册的bean实例。根据bean的配置情况,如果是singleton模式将返回一个共享实例,否则将返回一个新建的实例,如果没有找到指定bean,该方法可能会抛出异常
// <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;
// 返回给定名称的bean的Class,如果没有找到指定的bean实例,则排除NoSuchBeanDefinitionException异常 String[] getAliases(String name);// 根据实例的名字获取实例的别名 }
BeanFactory最常见的实现类为XmlBeanFactory,可以从classpath或文件系统等获取资源。
File file = new File("fileSystemConfig.xml"); Resource resource = new FileSystemResource(file); BeanFactory beanFactory = new XmlBeanFactory(resource); Resource resource = new ClassPathResource("classpath.xml"); BeanFactory beanFactory = new XmlBeanFactory(resource);
ApplicationContext
BeanFactory是Spring的心脏,ApplicationContext就是完整的躯体,ApplicationContext由BeanFactory派生而来,提供更多面向实际应用的功能。在BeanFactory中,需要以编程的方式实现,而在ApplicationContext中则可以通过配置实现。

BeanFactorty接口提供配置框架及基本功能,但是无法支持spring的aop功能和web应用。而ApplicationContext接口作为BeanFactory的派生,提供BeanFactory所有的功能。而且ApplicationContext还在功能上做扩展,相较于BeanFactorty,ApplicationContext还提供以下的功能:
(1)MessageSource, 提供国际化的消息访问
(2)资源访问,如URL和文件 :Resource rs = ctx. getResource(“classpath:config.properties”)
(3)事件传播特性,即支持aop特性
(4)载入多个(有继承关系)上下文 ,使得每一个上下文都专注于一个特定的层次,比如应用的web层
ApplicationContext:是IOC容器另一个重要接口, 继承BeanFactory的基本功能, 也继承容器的高级功能,如:MessageSource(国际化资源接口)、ResourceLoader(资源加载接口)、ApplicationEventPublisher(应用事件发布接口)等。
Spring为ApplicationContext提供3种实现,分别是ClassPathXmlApplicationContext、FileSystemXmlApplicationContext、XmlWebApplicationContext,其中XmlWebApplicationContext是专为Web工程定制的。
二者区别
1.BeanFactroy采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化,这样就不能发现一些存在的Spring的配置问题。而ApplicationContext则相反,它是在容器启动时,一次性创建了所有的Bean。在容器启动时,可以发现Spring中存在的配置错误。
BeanFacotry延迟加载,如果Bean的某一个属性没有注入,BeanFacotry加载后,直至第一次使用调用getBean方法才会抛出异常;而ApplicationContext则在初始化自身是检验,有利于检查所依赖属性是否注入;
应用上下文则会在上下文启动后预载入所有的单实例Bean。通过预载入单实例bean ,确保当需要的时候,就不用等待,因为它们已经创建好了。
2.BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但两者之间的区别是:BeanFactory需要手动注册而ApplicationContext则是自动注册。(Applicationcontext比 beanFactory 加入一些更好使用的功能。
BeanFactory和FactoryBean的区别
BeanFactory是接口,提供了IOC容器最基本的形式,给具体的IOC容器的实现提供规范,在Spring中,所有的Bean都是由BeanFactory(也就是IOC容器)来进行管理的。
BeanFactory,以Factory结尾,表示它是一个工厂类(接口), 它负责生产和管理bean的一个工厂。在Spring中,BeanFactory是IOC容器的核心接口,它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。BeanFactory只是个接口,并不是IOC容器的具体实现,
Spring容器给出了很多种实现,如 DefaultListableBeanFactory、XmlBeanFactory、ApplicationContext等,其中XmlBeanFactory就是常用的一个,该实现将以XML方式描述组成应用的对象及对象间的依赖关系。XmlBeanFactory类将持有此XML配置元数据,并用它来构建一个完全可配置的系统或应用。
Spring为此提供了一个org.springframework.bean.factory.FactoryBean的工厂类接口,用户可以通过实现该接口定制实例化Bean的逻辑。
FactoryBean以Bean结尾,表示是一个Bean,不同于普通Bean的是:它是实现了FactoryBean<T>接口的Bean,根据该Bean的ID从BeanFactory中获取的实际上是FactoryBean的getObject()返回的对象,而不是FactoryBean本身,如果要获取FactoryBean对象,请在id前面加一个&符号来获取。
例如自己实现一个FactoryBean,功能:用来代理一个对象,对该对象的所有方法做一个拦截,在调用前后都输出一行LOG,模仿ProxyFactoryBean的功能。
/** * my factory bean<p> * 代理一个类,拦截该类的所有方法,在方法的调用前后进行日志的输出 * @author daniel.zhao * */ public class MyFactoryBean implements FactoryBean<Object>, InitializingBean, DisposableBean { private static final Logger logger = LoggerFactory.getLogger(MyFactoryBean.class); private String interfaceName; private Object target; private Object proxyObj; @Override public void destroy() throws Exception { logger.debug("destroy......"); } @Override public void afterPropertiesSet() throws Exception { proxyObj = Proxy.newProxyInstance( this.getClass().getClassLoader(), new Class[] { Class.forName(interfaceName) }, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { logger.debug("invoke method......" + method.getName()); logger.debug("invoke method before......" + System.currentTimeMillis()); Object result = method.invoke(target, args); logger.debug("invoke method after......" + System.currentTimeMillis()); return result; } }); logger.debug("afterPropertiesSet......"); } @Override public Object getObject() throws Exception { logger.debug("getObject......"); return proxyObj; } @Override public Class<?> getObjectType() { return proxyObj == null ? Object.class : proxyObj.getClass(); } @Override public boolean isSingleton() { return true; } public String getInterfaceName() { return interfaceName; } public void setInterfaceName(String interfaceName) { this.interfaceName = interfaceName; } public Object getTarget() { return target; } public void setTarget(Object target) { this.target = target; } public Object getProxyObj() { return proxyObj; } public void setProxyObj(Object proxyObj) { this.proxyObj = proxyObj; } }
XML-Bean配置如下
<bean id="fbHelloWorldService" class="com.ebao.xxx.MyFactoryBean"> <property name="interfaceName" value="com.ebao.xxx.HelloWorldService" />
<property name="target" ref="helloWorldService" /> </bean>
Junit Test class
@RunWith(JUnit4ClassRunner.class) @ContextConfiguration(classes = { MyFactoryBeanConfig.class }) public class MyFactoryBeanTest { @Autowired private ApplicationContext context; /** * 测试验证FactoryBean原理,代理一个servcie在调用其方法的前后,打印日志亦可作其他处理 * 从ApplicationContext中获取自定义的FactoryBean * context.getBean(String beanName) ---> 最终获取到的Object是FactoryBean.getObejct(), * 使用Proxy.newInstance生成service的代理类 */ @Test public void testFactoryBean() { HelloWorldService helloWorldService = (HelloWorldService) context.getBean("fbHelloWorldService"); helloWorldService.getBeanName(); helloWorldService.sayHello(); } }
参考:
https://www.cnblogs.com/aspirant/p/9082858.html
https://www.cnblogs.com/xiaoxi/p/5850095.html
浙公网安备 33010602011771号