`
234390216
  • 浏览: 10195390 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
博客专栏
A5ee55b9-a463-3d09-9c78-0c0cf33198cd
Oracle基础
浏览量:460912
Ad26f909-6440-35a9-b4e9-9aea825bd38e
springMVC介绍
浏览量:1771975
Ce363057-ae4d-3ee1-bb46-e7b51a722a4b
Mybatis简介
浏览量:1395597
Bdeb91ad-cf8a-3fe9-942a-3710073b4000
Spring整合JMS
浏览量:393946
5cbbde67-7cd5-313c-95c2-4185389601e7
Ehcache简介
浏览量:678297
Cc1c0708-ccc2-3d20-ba47-d40e04440682
Cas简介
浏览量:529358
51592fc3-854c-34f4-9eff-cb82d993ab3a
Spring Securi...
浏览量:1178860
23e1c30e-ef8c-3702-aa3c-e83277ffca91
Spring基础知识
浏览量:462249
4af1c81c-eb9d-365f-b759-07685a32156e
Spring Aop介绍
浏览量:150212
2f926891-9e7a-3ce2-a074-3acb2aaf2584
JAXB简介
浏览量:66921
社区版块
存档分类
最新评论

使用FactoryBean接口实现自定义bean初始化

阅读更多

使用FactoryBean接口实现自定义bean初始化

 

       本文所要介绍的FactoryBeanSpring中定义的一个接口,当把它的实现类定义为BeanFactory中的一个bean,我们在获取其对应的bean时实际上获取的是FactoryBean所包含的那个对象,而不是它本身。我们先来看一下FactoryBean的定义。

public interface FactoryBean<T> {
 
   /**
    * 获取实际要返回的bean对象。
    * @return
    * @throws Exception
    */
   T getObject() throws Exception;
 
   /**
    * 获取返回的对象类型
    * @return
    */
   Class<?> getObjectType();
 
   /**
    * 是否单例
    * @return
    */
   boolean isSingleton();
 
}

 

 

       我们可以看到FactoryBean是使用了泛型的,表示其对应产生的Bean是什么类型的对象。我们来看一个实现。

public class UserFactoryBean implements FactoryBean<User> {
 
   private User user;
 
   @Override
   public User getObject() throws Exception {
      if (user == null) {
         synchronized (this) {
            if (user == null) {
                User user = new User();
                user.setId(1);
                user.setName("张三");
                this.user = user;
            }
         }
      }
      returnuser;
   }
 
   @Override
   public Class<?> getObjectType() {
      return User.class;
   }
 
   @Override
   public boolean isSingleton() {
      return true;
   }
  
}

 

 

       上面代码中定义了一个UserFactoryBean,用以产生一个单例的User对象。可以看到,我们在getObject()方法中使用了同步块来保证产生的bean永远是同一个对象。其实这个并不是必须的。在初始化时BeanFactory调用FactoryBean创建bean时就是同步的,而且BeanFactory创建bean时默认是单例的,也就意味着FactoryBeangetObject方法在BeanFactory中定义为单例的时候只会调用一次。但有一种情况例外,那就是如果定义bean时指定了“lazy-init=true”时,那就意味着该bean只有在用到的时候才会进行初始化,这个时候如果刚好两个线程同时需要使用,就会出现在两个线程中同时调用FactoryBeangetObject方法进行bean的初始化,如不加控制就会出现两个实例。为保证只有一个实例,getObject方法内部需要是同步的。

       此外,需要注意的是FactoryBeanisSingleton方法返回结果表示当前FactoryBean产生的bean是否是单例形式,即每次请求getObject()方法返回的是否都是同一个bean对象。其实FactoryBean更多的是在Spring内部使用,isSingleton只是用来表示当前返回的bean对象是否可以用BeanFactory缓存的一个标志。

       上面示例对象的Spring配置文件如下:

       <bean id="userFactoryBean" class="com.xxx.spring.factorybean.UserFactoryBean" lazy-init="false"/>

 

       对于一个FactoryBean接口实现类定义的bean其实Spring将实例化两个bean,一个是FactoryBean本身对应的bean,另一个是FactoryBean产生的对象对应的bean。所以当我们在通过注解方式注入一个FactoryBean实例对应的bean时,既可以把它当做一个FactoryBean进行注入,也可以把它当做一个对应产生的实例进行注入。而如果是自己直接从ApplicationContext中获取的话,则直接通过FactoryBean实现类定义的bean名称获取到的是FactoryBean实现类产生的对象。如在上面示例中,如果我们通过ApplicationContextgetBean(“userFactoryBean”)获取到的就将是对应产生的User对象,如果我们需要获取到对应的FactoryBean本身,则可以在对应的FactoryBean实现类定义的bean名称前加上“&”进行获取,如上如果我们要获取到UserFactoryBean本身,则可以通过ApplicationContextgetBean(“&userFactoryBean”)。如果是通过类型获取,就可以直接通过User类型或者UserFactoryBean类型获取到对应的bean对象了。

 

(注:本文是基于Spring3.1.0所写)

 

 

 

 

 

 

 

 

 

分享到:
评论
2 楼 234390216 2015-03-04  
zslin2011 写道
我感觉你说的有问题。
即使FactoryBean使用了“lazy-init=true”配置,getObject方法也不需要同步。因为应用程序需要获取bean时是委托Spring框架的,Spring框架完全可以控制只调用一次getObject。

其实文中已经解释的很清楚了。lazy-init=true时,如果同时有两个以上的线程需要引用它时,那就意味着Spring会同时调用多次getObject()方法。Spring要缓存对应的对象,也需要从getObject()返回了对应的对象后才能缓存,要不然拿什么缓存呢?并发问题就可能这样产生了。
1 楼 zslin2011 2015-03-03  
我感觉你说的有问题。
即使FactoryBean使用了“lazy-init=true”配置,getObject方法也不需要同步。因为应用程序需要获取bean时是委托Spring框架的,Spring框架完全可以控制只调用一次getObject。

相关推荐

    Spring 3 Reference中文

    4.6 自定义bean 的性质. 69 4.6.1 生命周期回调. 69 4.6.1.1 初始化回调 70 4.6.1.2 销毁回调.. 70 4.6.1.3 默认的初始化和销毁方法 71 4.6.1.4 组合生命周期机制.. 72 4.6.1.5 启动...

    Spring中文帮助文档

    3.3.4. 延迟初始化bean 3.3.5. 自动装配(autowire)协作者 3.3.6. 依赖检查 3.3.7. 方法注入 3.4. Bean的作用域 3.4.1. Singleton作用域 3.4.2. Prototype作用域 3.4.3. Singleton beans和prototype-bean的...

    Spring API

    3.3.4. 延迟初始化bean 3.3.5. 自动装配(autowire)协作者 3.3.6. 依赖检查 3.3.7. 方法注入 3.4. Bean的作用域 3.4.1. Singleton作用域 3.4.2. Prototype作用域 3.4.3. Singleton beans和prototype-bean的...

    Spring-Reference_zh_CN(Spring中文参考手册)

    3.3.5. 延迟初始化bean 3.3.6. 自动装配(autowire)协作者 3.3.6.1. 设置Bean使自动装配失效 3.3.7. 依赖检查 3.3.8. 方法注入 3.3.8.1. Lookup方法注入 3.3.8.2. 自定义方法的替代方案 3.4. bean的作用域 3.4.1. ...

    spring chm文档

    3.3.5. 延迟初始化bean 3.3.6. 自动装配(autowire)协作者 3.3.7. 依赖检查 3.3.8. 方法注入 3.4. bean的作用域 3.4.1. Singleton作用域 3.4.2. Prototype作用域 3.4.3. 其他作用域 3.4.4. 自定义作用域 ...

    Spring 2.0 开发参考手册

    3.3.5. 延迟初始化bean 3.3.6. 自动装配(autowire)协作者 3.3.7. 依赖检查 3.3.8. 方法注入 3.4. bean的作用域 3.4.1. Singleton作用域 3.4.2. Prototype作用域 3.4.3. 其他作用域 3.4.4. 自定义作用域 ...

    Spring面试题

    每个 bean 的定义都可以是 POJO (用类名和 JavaBean 初始化属性定义) 或 FactoryBean。FactoryBean 接口为使用 Spring 框架构建的应用程序添加了一个间接的级别。 IOC 示例 理解控制反转最简单的方式就是看它的...

    Spring攻略(第二版 中文高清版).part2

    2.7 自定义Bean初始化和析构 72 2.7.1 问题 72 2.7.2 解决方案 72 2.7.3 工作原理 72 2.8 用Java Config简化XML配置 77 2.8.1 问题 77 2.8.2 解决方案 77 2.8.3 工作原理 77 2.9 使Bean感知容器 ...

    Spring攻略(第二版 中文高清版).part1

    2.7 自定义Bean初始化和析构 72 2.7.1 问题 72 2.7.2 解决方案 72 2.7.3 工作原理 72 2.8 用Java Config简化XML配置 77 2.8.1 问题 77 2.8.2 解决方案 77 2.8.3 工作原理 77 2.9 使Bean感知容器 ...

    spring3.1中文参考文档

    spring3.1中文参考文档,南磊翻译,现在有4章,目录如下: 第一部分 Spring framework概述............................2.5.3.2 使用组件定义bean的元数据..............................................................

Global site tag (gtag.js) - Google Analytics