BeanFactory

BeanFactory是Spring中工厂的顶层接口,也是IOC容器的核心接口,BeanFactory中定义了管理Bean的通用方法,职责包括实例化、定位、配置应用程序中的对象以及建立这些对象的依赖。BeanFactory只是一个接口,并不是IOC容器的具体实现。

常用方法如下:

  • getBean(String name): Spring容器中获取对应Bean对象的方法,如存在,则返回该对象
  • containsBean(String name):Spring容器中是否存在该对象
  • isSingleton(String name):通过beanName是否为单例对象
  • isPrototype(String name):判断bean对象是否为多例对象
  • isTypeMatch(String name, ResolvableType typeToMatch):判断name值获取出来的bean与typeToMath是否匹配
  • getType(String name):获取Bean的Class类型
  • getAliases(String name):获取name所对应的所有的别名

主要的实现类:

  • DefaultListableBeanFactory:Spring默认的工厂类
  • XmlBeanFactory:前期使用XML配置用的比较多的时候用的Bean工厂
  • ClassPathXmlApplicationContext:XML解析上下文对象,用户创建Bean对象我们早期写Spring的时候用的就是他

BeanFactory部分源码

public interface BeanFactory {//对FactoryBean的转义定义,因为如果使用bean的名字检索FactoryBean得到的对象是工厂生成的对象,//如果需要得到工厂本身,需要转义String FACTORY_BEAN_PREFIX = "&";//根据bean的名字,获取在IOC容器中得到bean实例Object getBean(String name) throws BeansException;//根据bean的名字和Class类型来得到bean实例,增加了类型安全验证机制。 T getBean(String name, @Nullable Class requiredType) throws BeansException;.......//提供对bean的检索,看看是否在IOC容器有这个名字的beanboolean containsBean(String name);//根据bean名字得到bean实例,并同时判断这个bean是不是单例boolean isSingleton(String name) throws NoSuchBeanDefinitionException;.......//得到bean实例的Class类型@NullableClass getType(String name) throws NoSuchBeanDefinitionException;//得到bean的别名,如果根据别名检索,那么其原名也会被检索出来String[] getAliases(String name);}

BeanFactory的使用场景

  • 从IOC容器中获取Bean对象(byName 或 byType)
  • 检索IOC容器中是否包含指定的Bean对象
  • 判断Bean对象是否为单例

FactoryBean

FactoryBean也是一个Bean,但该Bean是一个能生成或修饰对象生成的工厂Bean,他的实现与设计模式中的工厂模式和修饰器模式类似,用户可以通过实现该接口来自定义该Bean接口的实例化过程。这里可能会有疑惑为什么不能在XML文件中配置Bean,而要使用FactoryBean去创建Bean,这里可以分两点:

  1. 在某些情况下实例化Bean过程比较复杂,如果使用传统的方式,则需要提供大量的配置信息,配置方式的灵活性受限,如果采用编码的方式可能会得到一个简单的方案。
  2. 第三方库不能直接注册到Spring容器当中,于是可以实现FactoryBean接口,然后给出自己对象的实例化代码即可。

常用方法如下:

  • T getObject():返回实例
  • Class getObjectType();:返回该装饰对象的Bean的类型
  • default boolean isSingleton():Bean是否为单例

接下来简单展示一下代码示例

在XML文件中配置两个Bean

两种Bean的具体代码

public class Person {private int age;private String name;public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}}
public class PersonFactoryBean implements FactoryBean {private String init;public void setInit(String init) {this.init = init;}@Overridepublic Person getObject() throws Exception {//处理初始化内容String[] split = init.split(",");Person person = new Person();String strAge = split[0];String name = split[1];person.setAge(Integer.parseInt(strAge));person.setName(name);return person;}@Overridepublic Class getObjectType() {return Person.class;}}

main方法测试

public class Main {public static void main(String[] args) {ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:application.xml");//通过xml配置创建的BeanPerson person = context.getBean("person", Person.class);System.out.println(person.getName());//通过FactoryBean创建的BeanPerson personByFactoryBean = context.getBean("personFromFactoryBean", Person.class);System.out.println(personByFactoryBean.getName());}}

运行结果如下

小明
小红

FactoryBean的使用场景

在Spring中最经典的一个应用就是用来创建AOP的代理对象。AOP实际上就是Spring在运行时创建一个代理对象,而不是一开始就定义好的,或者说AOP代理对象通过Java的反射机制在运行时创建了一个代理对象,在代理对象的目标方法中根据业务需求织入了相应的方法,在个对象在Spring中就是ProxyFactoryBean