BeanFacory
字面理解:以Factory结尾,是一个工厂接口,用于管理bean工厂。
作用:
1)实例化 (Instance)
2)定位 (缓存Map beanId->Instance)
3)建立bean之间的依赖关系
Resource resource = new FileSystemResource("spring.xml");
BeanFactory beanFactory = new XmlBeanFactory(resource);
ClassPathResource resource = new ClassPathResource ("spring.xml");
BeanFactory beanFactory(resource);
Application context = new ClassPathXmlApplicationContext(new String[]{"partOne.xml","paryTwo.xml"});
BeanFactory beanFactory =context;
如果是采用微服务框架,获取ApplicaitonContext的方式可以采用下面这种:
public ApplicationContextHelper implements ApplicationContextAware{
@Override
}
拿到beanFactory,接着使用getBean(String beanName)方法就可以取得bean的实例;
BeanFactory方法
1 boolean containsBean(String beanName)
判断工厂中是否包含给定名称的bean定义,若有则返回true
2 Object getBean(String)
返回给定名称注册的bean实例。根据bean的配置情况,如果是singleton模式将返回一个共享实例,否则将返回一个新建的实例,如果没有找到指定bean,该方法可能会抛出异常。
3 Object getBean(String, Class) 返回以给定名称注册的bean实例,并转换为给定class类型。
4 Class getType(String name) 返回给定名称的bean的Class,如果没有找到指定的bean实例,则排除NoSuchBeanDefinitionException异常。
5 boolean isSingleton(String) 判断给定名称的bean定义是否为单例模式。
6 String[] getAliases(String name) 返回给定bean名称的所有别名。
FactoryBean
字面意思:以Bean为结尾,是一个Bean。不同于普通Bean该bean可以生产Bean。
作用:通过编码的方式配置bean,可以避免复杂的配置。
-
传统采用xml配置一个bean的方式,Spring采用反射机制根据<bean>标签中class属性指定实现一个类的实例化并装配成bean。在属性特别多的时候需要编写大量的配置信息,这种场景下配置方式的灵活性受限。
-
编码方式注册bean能解决上述问题。Spring提供了org.springframwork.bean.factory.FactoryBean接口,用户可以通过该接口定制实例化Bean的逻辑。Spring框架自身就提供了70+FactoryBean的实现。它们隐藏了实例化一些复杂Bean的细节,给上层应用带来了便利。
接口定义:
public interface FactoryBean<T> {
@Nullable
T getObject() throws Exception;//返回由FactoryBean创建的bean实例,如果isSingleton()返回true,则该实例会放到Spring容器中单实例缓存池中。
@Nullable
Class<?> getObjectType();//返回FactoryBean创建的bean类型。
default boolean isSingleton() {
return true;
}//返回由FactoryBean创建的bean实例的作用域是singleton还是prototype。
}
具体实例:
当配置文件中<bean>的class属性配置的实现类是FactoryBean时,通过 getBean()方法返回的不是FactoryBean本身,而是FactoryBean#getObject()方法所返回的对象,相当于FactoryBean#getObject()代理了getBean()方法。例如:如果使用传统方式配置下面Car的<bean>时,Car的每个属性分别对应一个<property>元素标签。
public class Car {
private int maxSpeed ;
private String brand ;
private double price ;
// get/set方法l略
}
如果用FactoryBean的方式实现就会灵活一些,下例通过逗号分割符的方式一次性地为Car的所有属性指定配置值:
public class CarFactoryBean implements FactoryBean<Car> {
private String carInfo ;
public Car getObject () throws Exception {
Car car = new Car () ;
String [] infos = carInfo .split ( "," ) ;
car.setBrand ( infos [ 0 ]) ;
car.setMaxSpeed ( Integer. valueOf ( infos [ 1 ])) ;
car.setPrice ( Double. valueOf ( infos [ 2 ])) ;
return car;
}
public Class<Car> getObjectType () {
return Car. class ;
}
public boolean isSingleton () {
return false ;
}
public String getCarInfo () {
return this . carInfo ;
}
// 接受逗号分割符设置属性信息
public void setCarInfo ( String carInfo ) {
this . carInfocarInfo = carInfo;
}
}
有了这个CarFactoryBean后,就可以在配置文件中使用下面这种自定义的配置方式配置Car Bean了:
<bean id="car" class="com.test.factorybean.CarFactoryBean" carInfo="超级跑车,400,2000000"/>
当调用getBean("car") 时,Spring通过反射机制发现CarFactoryBean实现了FactoryBean的接口,这时Spring容器就调用接口方法CarFactoryBean#getObject()方法返回。如果希望获取CarFactoryBean的实例,则需要在使用getBean(beanName) 方法时在beanName前显示的加上 "&" 前缀,例如getBean("&car")。
网友评论