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

使用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。

相关推荐

    SSH笔记-通过实现FactoryBean接口来创建 Bean

    在Spring框架中,`FactoryBean`接口是一个非常重要的组件,它允许我们自定义Bean的创建逻辑,这在处理复杂对象的实例化或者需要特定初始化步骤时尤其有用。本笔记将详细探讨如何通过实现`FactoryBean`接口来创建Bean...

    Spring源码学习六:bean初始化1

    在本篇文章中,我们将深入探讨Spring源码中关于Bean初始化的过程,特别是`finishBeanFactoryInitialization()`方法和`preInstantiateSingletons()`方法。 首先,`finishBeanFactoryInitialization(Confi‌...

    FactoryBean代码最简实现

    这样,我们可以在`getObject()`方法中实现复杂的逻辑,如初始化、依赖注入等。 首先,我们需要了解`FactoryBean`接口的基本结构。它主要有两个核心方法: 1. `Object getObject() throws Exception;` 这个方法...

    Spring实例化Bean顺序

    9. **FactoryBean**:Spring的`FactoryBean`允许自定义Bean的创建方式。`FactoryBean`创建的对象被视为容器中的单个Bean,因此,它的实例化顺序遵循标准规则。 综上所述,Spring Bean的实例化顺序是一个复杂的过程...

    spring学习----工厂Bean

    3. **自定义类型转换**:当Spring需要将一个Bean的属性值转换为另一个类型时,可以使用FactoryBean来实现自定义的转换逻辑。 4. **第三方库集成**:某些库可能不支持Spring的依赖注入,或者它们的API需要特殊的初始...

    factory-bean-demo.7z

    1. **延迟初始化**: Spring容器在遇到`FactoryBean`时,不会立即创建bean,而是在需要该bean时才通过`getObject()`方法进行实例化,这实现了对象的延迟初始化。 2. **类型转换**: Spring会根据`getObjectType()`返回...

    Spring中的FactoryBean.rar

    例如,如果我们有一个复杂的对象需要在创建时执行特定的步骤,或者需要延迟初始化,那么使用FactoryBean就非常合适。 FactoryBean的应用场景主要包括: - 创建JDBC连接池,如C3P0、DBCP等,这些连接池可以通过...

    spring源码解析之FactoryBean相关测试代码demo

    在Spring框架中,`FactoryBean`是一个非常关键的接口,它允许我们自定义对象的创建方式,这在处理复杂依赖关系或需要特殊初始化逻辑时尤为有用。本篇将通过一个测试代码示例来深入解析`FactoryBean`的工作原理及其在...

    FactoryBean.zip

    `FactoryBean`的使用使得我们可以控制对象的创建过程,甚至可以在对象被Spring管理的同时,添加额外的初始化或者装配步骤。在这个"FactoryBean.zip"中,很可能是包含了关于如何使用`FactoryBean`来实现特定功能的...

    spring的FactoryBean增强我们的目标对象.rar

    这个接口使得我们可以实现自己的工厂逻辑,返回一个完全初始化、配置好的对象,甚至可以是带有额外增强功能的对象,比如代理类。在标题“spring的FactoryBean增强我们的目标对象.rar”中,提到的核心概念就是如何...

    spring bean的生命周期测试代码

    4. **容器回调**:在Bean初始化之后,Spring容器可能会调用自己的回调方法,如`BeanPostProcessor`接口实现的`postProcessBeforeInitialization()`和`postProcessAfterInitialization()`方法,允许自定义逻辑进一步...

    Spring框架中Bean的生命周期 Spring中Bean有几种作用域

    在Spring框架中,Bean的生命周期管理和作用域是其核心特性之一,它们对于理解Spring如何管理对象的创建、初始化、使用以及销毁至关重要。首先,我们来深入探讨Bean的生命周期。 Spring中的Bean生命周期主要分为两个...

    Spring源码学习八:常用的扩展接口详解1

    `FactoryBean`接口允许开发者自定义Bean的实例化过程。通过实现`getObject()`方法,我们可以控制Spring容器加载我们期望的Bean。这个接口特别适用于那些需要特殊初始化逻辑或非标准实例化的对象。 6. **...

    spring资料5

    通过实现FactoryBean接口,你可以控制实例化对象的具体过程,包括任何复杂的依赖注入或者初始化步骤。例如,如果你有一个数据库连接池,可能需要在创建连接时进行配置,这时可以使用FactoryBean来创建和配置这些连接...

    通过@Autowired注解注入bean的顺序,以及@bean注入.rar

    而传统的`factoryBean`则是通过实现`FactoryBean`接口来创建bean,这提供了更大的灵活性,但使用起来相对复杂。 结合`@Service`注解,它是Spring Data JPA和其他服务层组件常用的注解。`@Service`通常用于标记业务...

    实验一:Spring IoC中Bean的装置的jar包

    除了这些基本的Bean配置,Spring还提供了许多高级功能,如Prototype作用域(每次请求创建新的Bean实例)、Lazy初始化(只有在实际使用时才初始化Bean)、FactoryBean(用于自定义Bean的创建逻辑)等。此外,Bean后...

    Spring笔记(第三次)1

    最后,Spring提供了一种更灵活的机制——`BeanPostProcessor`接口,它允许在bean初始化前后进行拦截和处理。`BeanPostProcessor`有两个关键方法:`postProcessBeforeInitialization()`和`...

    spring工程需要的四个核心jar包之beans包

    `InitializingBean`和`DisposableBean`接口分别提供了`afterPropertiesSet()`和`destroy()`方法,使得开发者能够自定义Bean的初始化和销毁逻辑。 - 使用`@PostConstruct`和`@PreDestroy`注解也能实现相同功能,这两...

    Spring IOC设计原理解析.docx

    3. `FactoryBean`允许自定义Bean的创建逻辑,`AbstractBeanFactory`在获取Bean时会检查是否是FactoryBean并调用其`getObject()`方法。 4. `BeanPostProcessor`可以定制Bean实例化后的处理,`...

    自定义xml标签

    关于FactoryBean的使用,它允许我们创建具有复杂生命周期和初始化逻辑的bean。在自定义标签的场景中,我们可能希望对从标签中获取的内容进行额外的处理或包装。FactoryBean可以通过`getObject()`方法返回最终的bean...

Global site tag (gtag.js) - Google Analytics