Spring学习笔记

3.2.3.2. 通过静态工厂方法创建Bean

当你定义一个使用静态工厂方法创建的bean,同时使用class属性指定包含静态工厂方法的类,这个时候需要factory-method属性来指定工厂方法名。Spring调用这个方法(包含一组可选的参数)并返回一个有效的对象,之后这个对象就完全和构造方法创建的对象一样。用户可以使用这样的bean定义在遗留代码中调用静态工厂。

下面是一个bean定义的例子,声明这个bean要通过factory-method指定的方法创建。注意这个bean定义并没有指定返回对象的类型,只指定包含工厂方法的类。在这个例子中,createInstance 必须是static方法 .

<bean id="exampleBean"
      class="examples.ExampleBean2"
      factory-method="createInstance"/>

//

3.2.3.3. 通过实例工厂方法创建bean

使用一个实例工厂方法(非静态的)创建bean和使用静态工厂方法非常类似,调用一个已存在的bean(这个bean应该是工厂类型)的工厂方法来创建新的bean

使用这种机制,class属性必须为空,而且factory-bean属性必须指定一个bean的名字,这个bean一定要在当前的bean工厂或者父bean工厂中,并包含工厂方法。 而工厂方法本身仍然要通过factory-method属性设置。

下面是一个例子:

<!-- The factory bean, which contains a method called
     createInstance -->
<bean id="myFactoryBean"
      class="...">
  ...
</bean>
<!-- The bean to be created via the factory bean -->
<bean id="exampleBean"
      factory-bean="myFactoryBean"
      factory-method="createInstance"/>

同过某工厂获得该BEAN,没有class属性

//

·         通常你可以信任Spring做了正确的事情。它会在BeanFactory装载的时候检查出错误,包括对不存在bean的引用和循环引用。它会尽可能晚地设置属性和解决依赖(比如创建那些需要的依赖),也就是在bean真正被创建的时候。这就意味着:就算一个BeanFactory被正确地装载,稍后当你请求一个bean的时候,如果创建那个bean或者它的依赖的时候出现了错误,这个BeanFactory也会抛出一个异常。比如,如果一个bean抛出一个异常作为缺少或非法属性的结果,这样的情况就会发生。这种潜在地推迟一些配置错误可见性的行为正是ApplicationContext默认预实例化singleton bean的原因。以前期的时间和内存为代价在beans真正需要之前创建它们,你就可以在ApplicationContext创建的时候找出配置错误,而不是在后来。如果你愿意,你也可以覆盖这种默认的行为,设置这些singleton beanlazy-load不是预实例化的)。

//

 

现在考虑一下不用构造函数,而是调用一个静态工厂方法来返回一个对象的实例:

<bean id="exampleBean" class="examples.ExampleBean"
      factory-method="createInstance">
    <constructor-arg><ref bean="anotherExampleBean"/></constructor-arg>
    <constructor-arg><ref bean="yetAnotherBean"/></constructor-arg>
    <constructor-arg><value>1</value></constructor-arg>
</bean>

   
   
    
     
   
   
<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>
public class ExampleBean {

   
   
    
     
   
   
    ...

   
   
    
     
   
   
    // a private constructor
    private ExampleBean(...) {
      ...
    }
    
    // a static factory method
    // the arguments to this method can be considered the dependencies of the bean that
    // is returned, regardless of how those arguments are actually used.
    public static ExampleBean ExampleBean(AnotherBean anotherBean,
                                          YetAnotherBean yetAnotherBean, int i) {
        ExampleBean eb = new ExampleBean(...);
        // some other operations
        ...
        return eb;
    }
}

需要注意的是:静态工厂方法的参数由 constructor-arg元素提供,这和构造函数的用法是一样的。这些参数是可选的。重要的一点是工厂方法所返回的对象类型不一定和包含这个静态工厂方法的类一致,虽然上面这个例子中是一样的。前面所提到的实例工厂方法(non-static)用法基本上是一样的(除了使用factory-bean属性代替class属性),在这里就不再详细叙述了。 .

 

property 元素中定义的bean元素用来定义一个内联的bean,而不是引用BeanFactory其他地方定义的bean。内联bean定义不需要任何id定义

<bean id="outer" class="...">
    <!-- Instead of using a reference to target, just use an inner bean -->
    <property name="target">  属性为另一个BEAN的引用
      
      
        <bean class="com.mycompany.PersonImpl">
     
     
            <property name="name"><value>Tony</value></property>
     
     
            <property name="age"><value>51</value></property>
     
     
        </bean>
     
     
   </property>
</bean>

idref元素完全是一种简写和防止错误的方

///

3.3.3. 方法注入

对于大部分的用户来说,容器中多数的beansingleton的。当一个singletonbean需要同另一个singleton bean合作(使用)时,或者一个非singletonbean需要同另一个非singletonbean合作的时候,通过定义一个bean为另一个bean的属性来处理这种依赖的关系就足够了。然而当bean的生命周期不同的时候就有一个问题。想想一下一个singleton bean A,或许在每次方法调用的时候都需要使用一个non-singleton bean B。容器仅仅会创建这个singleton bean A一次,因此仅仅有一次的机会去设置它的属性。因此容器没有机会每次去为bean A提供新的bean B的实例。 一个解决这个问题的方法是放弃一些反向控制。Bean A可以通过实现 BeanFactoryAware知道容器的存在(参见这里)),使用编程的手段(参见这里)在需要的时候通过调用getBean("B")来向容器请求新的bean B实例。 因为bean的代码知道Spring并且耦合于Spring,所以这通常不是一个好的方案。 方法注入,BeanFactory的高级特性之一,可以以清洁的方式处理这种情况以及其他一些情况。

///

对于相对罕见的情况,beans之间的依赖不够直接(举例,当一个类中的静态初始块需要被触发,比如数据库驱动的注册),depends-on 元素可以用来在初始化使用这个元素的bean之前,强制一个或多个beans初始化。

<bean id="beanOne" class="ExampleBean" depends-on="manager">强迫manager先初始化
      
      
    <property name="manager"><ref local="manager"/></property>
</bean>

   
   
    
     
   
   
<bean id="manager" class="ManagerBean"/>

///

通过bean定义中的 dependency-check 属性来指定依赖检查,这个属性有以下的值。

 3.3. 依赖检查模式

模式

解释

none

不进行依赖检查。没有指定值的bean属性仅仅是没有设值。

simple

对基本类型和集合(除了合作者外,比如其他的bean,所有东西)进行依赖检查。

object

对合作者进行依赖检查。

all

对合作者,基本类型和集合都进行依赖检查

/3.8.1. PropertyPlaceholderConfigurer

可以动态覆盖么`??

PropertyPlaceholderConfigurer作为一个bean factory post-processor实现,可以用来将BeanFactory定义中的属性值放置到另一个单独的Java Properties格式的文件中。 这使得用户不用对BeanFactory的主XML定义文件进行复杂和危险的修改,就可以定制一些基本的属性(比如说数据库的urls,用户名和密码)。

考虑一个BeanFactory定义的片断,里面用占位符定义了DataSource

在下面这个例子中,定义了一个datasource,并且我们会在一个外部Porperties文件中配置一些相关属性。在运行时,我们为BeanFactory提供一个PropertyPlaceholderConfigurer,它将用Properties文件中的值替换掉这个datasource的属性值:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName"><value>${jdbc.driverClassName}</value></property>
    <property name="url"><value>${jdbc.url}</value></property>
    <property name="username"><value>${jdbc.username}</value></property>
    <property name="password"><value>${jdbc.password}</value></property>
</bean>

真正的值来自于另一个Properties格式的文件:

jdbc.driverClassName=org.hsqldb.jdbcDriver
jdbc.url=jdbc:hsqldb:hsql://production:9002
jdbc.username=sa
jdbc.password=root

如果要在BeanFactory中使用,bean factory post-processor必须手动运行:

XmlBeanFactory factory = new XmlBeanFactory(new FileSystemResource("beans.xml"));
PropertyPlaceholderConfigurer cfg = new PropertyPlaceholderConfigurer();
cfg.setLocation(new FileSystemResource("jdbc.properties"));
cfg.postProcessBeanFactory(factory);

 

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值