:BeanFactory是个Factory,也就是IOC容器或对象工厂,FactoryBean是个Bean。在Spring中,所有的Bean都是由BeanFactory(也就是IOC容器)来进行管理的。但对FactoryBean而言,这个Bean不是简单的Bean,而是一个能生产或者修饰对象生成的工厂Bean,它的实现与设计模式中的工厂模式和修饰器模式类似
1. BeanFactoryBeanFactory定义了IOC容器的最基本形式,并提供了IOC容器应遵守的的最基本的接口,也就是Spring IOC所遵守的最底层和最基本的编程规范。在Spring代码中,BeanFactory只是个接口,并不是IOC容器的具体实现,但是Spring容器给出了很多种实现,如 DefaultListableBeanFactory、XmlBeanFactory、ApplicationContext等,都是附加了某种功能的实现。
package org.springframework.beans.factory;
import org.springframework.beans.BeansException;
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);
}
2.FactoryBean
一般情况下,Spring通过反射机制利用的class属性指定实现类实例化Bean,在某些情况下,实例化Bean过程比较复杂,如果按照传统的方式,则需要在中提供大量的配置信息。配置方式的灵活性是受限的,这时采用编码的方式可能会得到一个简单的方案。Spring为此提供了一个org.springframework.bean.factory.FactoryBean的工厂类接口,用户可以通过实现该接口定制实例化Bean的逻辑。
FactoryBean接口对于Spring框架来说占用重要的地位,Spring自身就提供了70多个FactoryBean的实现。它们隐藏了实例化一些复杂Bean的细节,给上层应用带来了便利。从Spring3.0开始,FactoryBean开始支持泛型,即接口声明改为FactoryBean的形式
package org.springframework.beans.factory;
public interface FactoryBean<T> {
T getObject() throws Exception;
Class<?> getObjectType();
boolean isSingleton();
}
使用场景
说了这么多,为什么要有FactoryBean这个东西呢,有什么具体的作用吗?
FactoryBean在Spring中最为典型的一个应用就是用来创建AOP的代理对象。
我们知道AOP实际上是Spring在运行时创建了一个代理对象,也就是说这个对象,是我们在运行时创建的,而不是一开始就定义好的,这很符合工厂方法模式。更形象地说,AOP代理对象通过Java的反射机制,在运行时创建了一个代理对象,在代理对象的目标方法中根据业务要求织入了相应的方法。这个对象在Spring中就是——ProxyFactoryBean。
所以,FactoryBean为我们实例化Bean提供了一个更为灵活的方式,我们可以通过FactoryBean创建出更为复杂的Bean实例。
ProxyFactoryBean.java
@Override
@Nullable
public Object getObject() throws BeansException {
initializeAdvisorChain();
if (isSingleton()) {
return getSingletonInstance();
}
else {
if (this.targetName == null) {
logger.info("Using non-singleton proxies with singleton targets is often undesirable. " +
"Enable prototype proxies by setting the 'targetName' property.");
}
return newPrototypeInstance();
}
}
还有比如我们spring需要整合mybatis,在没有spring-mybatis的情况下(spring-mybatis会帮助你将MyBatis 代码无缝地整合到Spring 中),我们需要将mybatis核心类SqlSessionFactory注入到spring容器,那么思考使用最常用的两种方式:
注解,可是mybatis是个我们引用的独立的项目.与我们自己的项目源码无关,我们无法去修改它的源码,在它的源码上添加注解,所以不能使用注解的方法
xml,sqlSessionFacory需要注入许多的依赖,如果使用XML来配置,需要我们写大量的配置标签,非常不方便维护。
所以可以选择一个代理类去处理sqlSessionFacory,也就是我们在整合spring+mybatis时使用的SqlSessionFactoryBean,这个类是由mybatis提供的用来方便我们快速配置mybatis的factoryBean,通过这个类把很多繁琐的配置代码封装了起来,类似于装饰者模式,SqlSessionFactoryBean里面管理了sqlSessionFacory并且对他进行相关配置设置 *** 作,我们只需要将SqlSessionFactoryBean注入到spring容器中,并在在xml向这个factoryBean传入一些简单的配置信息,SqlSessionFactoryBean就会帮我们自动配置好sqlSessionFacory,很多复杂的配置都帮我们填充好了,然后我们就可以通过SqlSessionFactoryBean获取已经配置完成的sqlSessionFacory。
SqlSessionFactoryBean.java
/**
* {@inheritDoc}
*/
@Override
public SqlSessionFactory getObject() throws Exception {
if (this.sqlSessionFactory == null) {
afterPropertiesSet();
}
return this.sqlSessionFactory;
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)