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> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException;
.......
//提供对bean的检索,看看是否在IOC容器有这个名字的bean
boolean containsBean(String name);
//根据bean名字得到bean实例,并同时判断这个bean是不是单例
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
.......
//得到bean实例的Class类型
@Nullable
Class<?> 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,这里可以分两点:
- 在某些情况下实例化Bean过程比较复杂,如果使用传统的方式,则需要提供大量的配置信息,配置方式的灵活性受限,如果采用编码的方式可能会得到一个简单的方案。
- 第三方库不能直接注册到Spring容器当中,于是可以实现FactoryBean接口,然后给出自己对象的实例化代码即可。
常用方法如下:
- T getObject():返回实例
- Class<?> getObjectType();:返回该装饰对象的Bean的类型
- default boolean isSingleton():Bean是否为单例
接下来简单展示一下代码示例
在XML文件中配置两个Bean
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="person" class="com.zmt.factoryBeanDemo.entity.Person">
<property name="age" value="10"/>
<property name="name" value="小明"/>
</bean>
<bean id="personFromFactoryBean" class="com.zmt.factoryBeanDemo.factoryBean.PersonFactoryBean">
<property name="init" value="10,小红"/>
</bean>
</beans>
两种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<Person> {
private String init;
public void setInit(String init) {
this.init = init;
}
@Override
public 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;
}
@Override
public Class<?> getObjectType() {
return Person.class;
}
}
main方法测试
public class Main {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:application.xml");
//通过xml配置创建的Bean
Person person = context.getBean("person", Person.class);
System.out.println(person.getName());
//通过FactoryBean创建的Bean
Person personByFactoryBean = context.getBean("personFromFactoryBean", Person.class);
System.out.println(personByFactoryBean.getName());
}
}
运行结果如下
小明
小红
FactoryBean的使用场景
在Spring中最经典的一个应用就是用来创建AOP的代理对象。AOP实际上就是Spring在运行时创建一个代理对象,而不是一开始就定义好的,或者说AOP代理对象通过Java的反射机制在运行时创建了一个代理对象,在代理对象的目标方法中根据业务需求织入了相应的方法,在个对象在Spring中就是ProxyFactoryBean