Spring(十四):使用FactoryBean配置Bean
FactoryBean简介:
1)Spring中Bean包含两种一种是普通Bean,另外一种是FactoryBean。它们都受IOC容器管理,但是也有不同之处。
2)普通Bean与FactoryBean的区别:
a)普通的Bean只需要定义好,然后配置文件中定义并配置其依赖关系,就可以通过IOC容器的getBean获取到;
b)FactoryBean是实现了FactoryBean<T>接口的Bean,通过FactoryBean类的getBean方法直接获取到的并不是该FactoryBean实例,而是FactoryBean中方法getObject返回的对象。
c)FactoryBean的实例可以通过其他方法获取到,在通过getBean方法获取实例时在参数name前面加上“&”符号即可。
FactoryBean的接口定义如下:
public interface FactoryBean<T> { //获取FactoryBean初始化的Bean实例 T getObject() throws Exception; //获取Bean实例的类型 Class<?> getObjectType(); //判断是否是单例模式 default boolean isSingleton() { return true; } }
示例:
定义Category.java
package com.dx.spring.beans.factorybean; public class Category { private Integer id; private String name; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Category(Integer id, String name) { super(); this.id = id; this.name = name; } @Override public String toString() { return "Category [id=" + id + ", name=" + name + "]"; } }
定义CategoryFactoryBean.java
package com.dx.spring.beans.factorybean; import org.springframework.beans.factory.FactoryBean; public class CategoryFactoryBean implements FactoryBean<Category> { private String name; public void setName(String name) { this.name = name; } @Override public Category getObject() throws Exception { System.out.println(this.name); return new Category(1, "java spring"); } @Override public Class<?> getObjectType() { return Category.class; } @Override public boolean isSingleton() { return FactoryBean.super.isSingleton(); } }
新建spring bean配置文件bean-factorybean.xml:
<?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="category" class="com.dx.spring.beans.factorybean.CategoryFactoryBean"> <property name="name" value="hello factorybean"></property> </bean> </beans>
添加测试类Client.java并测试:
package com.dx.spring.beans.factorybean; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Client { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("bean-factorybean.xml"); Category category = (Category) ctx.getBean("category"); System.out.println(category); CategoryFactoryBean categoryFactoryBean = (CategoryFactoryBean) ctx.getBean("&category"); System.out.println(categoryFactoryBean); } }
打印信息为:
hello factorybean Category [id=1, name=java spring] com.dx.spring.beans.factorybean.CategoryFactoryBean@1e397ed7
实现原理:
声明:以下参考《Spring源码学习--FactoryBean实现原理》
当程序执行Category category = (Category) ctx.getBean("category");时,在AbstractBeanFactory中会进行一系列的操作:
getBean获取bean
@Override public Object getBean(String name) throws BeansException { return doGetBean(name, null, null, false); }
doGetBean中获取bean实例
protected <T> T doGetBean( final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException { .........//省略部分代码 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); .........//省略部分代码 return (T) bean; }
getObjectForBeanInstance中会选择bean实例是普通的Bean还是FactoryBean,同时通过判断name中是否有&来选择判断是或者FactoryBean还是其getObject方法中获取的bean
protected Object getObjectForBeanInstance( Object beanInstance, String name, String beanName, RootBeanDefinition mbd) { .........//省略部分代码 //判断bean类型是否是FactoryBean,或者name是否是以&开头,如果是则直接返回 if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) { return beanInstance; } //如果是则从getObjectFromFactoryBean中获取 if (object == null) { // Return bean instance from factory. FactoryBean<?> factory = (FactoryBean<?>) beanInstance; if (mbd == null && containsBeanDefinition(beanName)) { mbd = getMergedLocalBeanDefinition(beanName); } boolean synthetic = (mbd != null && mbd.isSynthetic()); object = getObjectFromFactoryBean(factory, beanName, !synthetic); } return object; }
getObjectFromFactoryBean接下来会执行FactoryBean的getObject方法获取bean了。
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) { .........//省略部分代码 Object object = doGetObjectFromFactoryBean(factory, beanName); .........//省略部分代码 return object; } private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName) throws BeanCreationException { Object object; .........//省略部分代码 //调用Factory的getObject方法 object = factory.getObject(); .........//省略部分代码 return object; }
基础才是编程人员应该深入研究的问题,比如:
1)List/Set/Map内部组成原理|区别
2)mysql索引存储结构&如何调优/b-tree特点、计算复杂度及影响复杂度的因素。。。
3)JVM运行组成与原理及调优
4)Java类加载器运行原理
5)Java中GC过程原理|使用的回收算法原理
6)Redis中hash一致性实现及与hash其他区别
7)Java多线程、线程池开发、管理Lock与Synchroined区别
8)Spring IOC/AOP 原理;加载过程的。。。
【+加关注】。