这几个接口实际获取的对象都是从当前线程的上下文中获取的(通过ThreadLocal) , 所以在Controller中直接属性注入相应的对象是线程安全的 。1 接口对比ObjectFactory@FunctionalInterfacepublic interface ObjectFactory<T> { T getObject() throws BeansException;}
就是一个普通的函数式对象接口 。
FactoryBeanpublic interface FactoryBean<T> { // 返回真实的对象 T getObject() throws Exception; // 返回对象类型 Class<?> getObjectType(); // 是否单例;如果是单例会将其创建的对象缓存到缓存池中 。boolean isSingleton();}
该接口就是一个工厂Bean , 在获取对象时 , 先判断当前对象是否是FactoryBean , 如果是再根据getObjectType的返回类型判断是否需要的类型 , 如果匹配则会调用getObject方法返回真实的对象 。该接口用来自定义对象的创建 。
注意:如果A.class 实现了FactoryBean , 如果想获取A本身这个对象则bean的名称必须添加前缀 '&' , 也就是获取Bean则需要ctx.getBean("&a")
当注入属性是ObjectFactory或者ObjectProvider类型时 , 系统会直接创建DependencyObjectProvider对象然后进行注入 , 只有在真正调用getObject方法的时候系统才会根据字段上的泛型类型进行查找注入 。
2 实际应用ObjectFactory在Spring源码中应用的比较多
2.1 创建Bean实例public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {// other codeif (mbd.isSingleton()) {//getSingleton方法的第二个参数就是ObjectFactory对象(这里应用了lamda表达式)sharedInstance = getSingleton(beanName, () -> {try {return createBean(beanName, mbd, args);} catch (BeansException ex) {// Explicitly remove instance from singleton cache: It might have been put there// eagerly by the creation process, to allow for circular reference resolution.// Also remove any beans that received a temporary reference to the bean.destroySingleton(beanName);throw ex;}});beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}// other code}}
这里的getSingleton方法就是通过不同的Scope(singleton , prototype , request , session)创建Bean;具体的创建细节都是交个ObjectFactory来完成 。
2.2 Servlet API注入【Spring中这两个对象ObjectFactory与FactoryBean接口你使用过吗?】在Controller中注入Request , Response相关对象时也是通过ObjectFactory接口 。
容器启动时实例化的上下文对象是AnnotationConfigServletWebServerApplicationContext;
调用在AbstractApplicationContext#refresh.postProcessBeanFactory
public class AnnotationConfigServletWebServerApplicationContext {protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {super.postProcessBeanFactory(beanFactory);if (this.basePackages != null && this.basePackages.length > 0) {this.scanner.scan(this.basePackages);}if (!this.annotatedClasses.isEmpty()) {this.reader.register(ClassUtils.toClassArray(this.annotatedClasses));}}}
super.postProcessBeanFactory(beanFactory)方法进入到ServletWebServerApplicationContext中
public class ServletWebServerApplicationContext extends GenericWebApplicationContext implements ConfigurableWebServerApplicationContext {@Overrideprotected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {beanFactory.addBeanPostProcessor(new WebApplicationContextServletContextAwareProcessor(this));beanFactory.ignoreDependencyInterface(ServletContextAware.class);registerWebApplicationScopes();}private void registerWebApplicationScopes() {ExistingWebApplicationScopes existingScopes = new ExistingWebApplicationScopes(getBeanFactory());WebApplicationContextUtils.registerWebApplicationScopes(getBeanFactory());existingScopes.restore();}}
WebApplicationContextUtils工具类
public abstract class WebApplicationContextUtils {public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory) {registerWebApplicationScopes(beanFactory, null);}public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory, @Nullable ServletContext sc) {beanFactory.registerScope(WebApplicationContext.SCOPE_REQUEST, new RequestScope());beanFactory.registerScope(WebApplicationContext.SCOPE_SESSION, new SessionScope());if (sc != null) {ServletContextScope appScope = new ServletContextScope(sc);beanFactory.registerScope(WebApplicationContext.SCOPE_APPLICATION, appScope);// Register as ServletContext attribute, for ContextCleanupListener to detect it.sc.setAttribute(ServletContextScope.class.getName(), appScope);}beanFactory.registerResolvableDependency(ServletRequest.class, new RequestObjectFactory());beanFactory.registerResolvableDependency(ServletResponse.class, new ResponseobjectFactory());beanFactory.registerResolvableDependency(HttpSession.class, new SessionObjectFactory());beanFactory.registerResolvableDependency(WebRequest.class, new WebRequestObjectFactory());if (jsfPresent) {FacesDependencyRegistrar.registerFacesDependencies(beanFactory);}}}
推荐阅读
- 纯洁有内涵的女孩名字 纯洁有内涵的女孩名字两个字
- 古风男孩名字儒雅有仙气 古风男孩名字儒雅有仙气两个字
- 网红瓜妈宣布离婚,直言从来没这么轻松过,自爆两个继女前期挑拨
- 好听洋气的女宝宝名字大全 好听洋气的女宝宝名字大全两个字
- Spring定义Controller接口的这些方式你肯定不知道
- 宝宝取名小名男孩子两个字 宝宝取名小名男孩子
- 两个字的公司名字霸气 两个字的公司名字霸气男
- SpringBoot实现多数据源配置详解
- 使用了Spring的事件机制真香!
- 高贵大气的女孩名字两个字 高贵大气的女孩名字