细说Spring——IoC详解(FactoryBean、方法注入和方法替换)

这篇文章我们主要来学习一下FactoryBean、方法注入和方法替换。

一、FactoryBean

先给出一下比较官方的定义:

A FactoryBean is a pattern to encapsulate interesting object construction logic in a
class. It might be used, for example, to encode the construction of a complex object 
graph in a reusable way. Often this is used to construct complex objects that have 
many dependencies. It might also be used when the construction logic itself is 
highly volatile and depends on the configuration. A FactoryBean is also useful to 
help Spring construct objects that it couldn’t easily construct itself. For example, in 
order to inject a reference to a bean that was obtained from JNDI, the reference 
must first be obtained. You can use the JndiFactoryBean to obtain this reference in 
a consistent way. You may inject the result of a FactoryBean’s getObject() method 
into any other property.

这段话的意思大致是:

FactoryBean是一种将有趣的对象构造逻辑封装在类中的模式。例如,它可以用于以
可重用的方式对复杂对象的构造进行编码。通常这被用来构造具有许多依赖关系的
复杂对象。当构建逻辑本身高度易失性并取决于配置时,也可能使用它。 
FactoryBean也可以帮助Spring构建它自己不容易构造的对象。例如,为了注入一个
从JNDI获得的bean的引用,必须首先获得引用。您可以使用JndiFactoryBean以一致
的方式获取此引用。您可以将FactoryBean的getObject()方法的结果注入任何其他
属性。

通俗的解释一下这段话的意思:当我们不想或不能使用Spring帮我们自动构建对象的时候,我们可以通过创建一个FactoryBean接口的实例,来自己实现对象的创建。

我们先来看一下FactoryBean接口:

public interface FactoryBean<T> {
    T getObject() throws Exception;
    Class<T> getObjectType();
    boolean isSingleton();
}
  • getObject()方法会返回该FactoryBean“生产”的对象实例,我们需要实现该方法以给出自己的对象实例化逻辑;
  • getObjectType()方法仅返回getObject()方法所返回的对象的类型,如果预先
    无法确定,则返回null
  • isSingleton()方法返回结果用于表明,工厂方法getObject()所“生
    产”的对象是否要以singleton形式存在于容器中。如果以singleton形式存在,则返回true,否则返回false

下面是使用FactoryBean创建对象的一个例子:
假设我们有一个Person对象,这个Person对象有两个属性,其中一个是Car,但是我们不想让Spring帮助我们创建这个Car类的实例,我们就可以自己实现一个MyCarFactoryBean来自己定义创建实例的逻辑。

Person类

public class Person { 
   private Car car ;
   private void setCar(Car car){ this.car = car;  } 
}

FactoryBean类

public class MyCarFactoryBean implements FactoryBean<Car>{

  public Car getObject(){   
    return new Car();
  }

  public Class<Car> getObjectType() { return Car.class ; } 

  public boolean isSingleton() { return false; }
}

然后我们就可以这样配置xml文件:

<bean class = "...MyCarFactoryBean"  id = "car"></bean>

<bean class = "...Person" id = "josh">
    <property name = "car" ref = "car"/>
</bean>

我们也可以通过注解的方法来实现上面的例子:

@Configuration 
public class CarConfiguration { 

  @Bean 
  public MyCarFactoryBean carFactoryBean(){ 
    return new Car();
  }

  @Bean
  public Person aPerson(){ 
    Person person = new Person();
    person.setCar( carFactoryBean().getObject());
    return person; 
  } 
}

通过上面的例子我们可以发现,在xml配置文件中我们通过正常的id引用,容器返回的是FactoryBean所“生产”的对象类型,而非FactoryBean实现本身。

二、方法注入

这里我主要推荐一个讲解方法注入讲解的特别详细的一个博客:Spring查找方法注入(Lookup method injection)的底层实现原理

三、方法替换

方法替换可以灵活替换或者说以新的方法实现覆盖掉原来某个方法的实现逻辑。
实现方法替换我们需要以下两个步骤:

  • 实现MethodReplacer接口
  • 替换目标Bean的方法

我们一步一步来,首先我们先创建一个MethodReplacer接口的实例,我们需要在实例中添加要替换的逻辑。

public class PersonOne {
    public Car getCar(){
        Car car=new Car();
        car.setBrand("宝马");
        return car;
    }
}

public class PersonTwo implements MethodReplacer{
    public Object reimplement(Object arg0,Method arg1,Object[] arg2){
        Car car=new Car();
        car.setBrand("美人豹");
        return car;
    }
}

上面的例子中,PersonTwo实现了MethodReplacer接口,有了要替换的逻辑之后,我们就可以把这个逻辑通过<replaced-method>配置到bean定义中,使其生效,我们现在要做的就是把PersonOnegetCar()方法替换为reimplemen()方法,配置如下:

<bean id="personTwo" class="....PersonTwo "/>  
<bean id="personOne " class=".....PersonOne "/>  
    <replaced-method name="getCar" replacer="PersonTwo"></replaced-method>  
</bean>  

猜你喜欢

转载自blog.csdn.net/q982151756/article/details/80404836