当前位置:网站首页>Don't tell beanfactory from factorybean

Don't tell beanfactory from factorybean

2020-12-06 07:05:38 osc_ vvylzpqs

 Stop BeanFactory and FactoryBean Stupid is not clear

Write it at the front

Spring series , I'm going to learn a little bit more deeply in the way of the following class diagram , So we go from BeanFactory and FactoryBean Let's start. .
 Stop BeanFactory and FactoryBean Stupid is not clear

Preface

as everyone knows , stay Spring There are two concepts that are particularly confusing , That's it BeanFactory and FactoryBean Two brothers . In the last article, we talked about BeanFactory, Its subject is Factory, The attributive is Bean, In other words, it's management Bean Our factory . We need to use some Bean You just need it to get . And for FactoryBean, Its subject is Bean, The attributive is Factory, So it's essentially a Bean, With others registered to Spring In container Bean equally , It's just , The Bean A special , It's production itself Bean Our factory ( It's like a woman is a person , But women are special , She can produce people ).

Scene Introduction

In the work , We often stress " Interface oriented programming ", But you want to : Although we can avoid coupling with implementation classes through interfaces , But there must be a way to associate the interface with the implementation class . If the implementation class is our own development, it is relatively simple : Through dependency injection , Let the container decouple the interface from the implementation class . But sometimes implementation classes are not developed by us , One case is that the implementation class is automatically generated at runtime based on some information , After generation, it should be handed over to container management ( such as mybatis Of mapper Proxy class for interface ), What about this situation ? Generally, we use the factory approach model (Factory-Method) To solve . The following code :

public interface AirConditioner {
  //  Air conditioning interface 
}

public class Car {
  private AirConditioner conditioner;
  public Car() {
    this.conditioner = AirConditionerFactory.getInstance();
    //  Or as follows 
    // this.conditioner = new AirConditionFactory.getInstance();
  }
  // getter setter  Method brief 
}

public class AirConditionerFactory {
  public static AirConditioner getInstance(){
    //  Dynamic generation AirConditioner The proxy class implementation of 
  }
  //  Or as follows 
  //public AirConditioner getInstance(){
    //  Dynamic generation AirConditioner The proxy class implementation of 
  //}
}

Spring Solution in

For the above, we use the factory method pattern to instantiate objects , stay Spring in IOC The container provides us with the corresponding support . We just need to inject the concrete implementation class of the interface returned by the factory into the object that depends on the interface . There are three ways to do it , As soon as we get to know .

Through the static factory method

public class AirConditionerFactory {
  public static AirConditioner getInstance(){
    //  Dynamic generation AirConditioner The proxy class implementation of 
  }
}

In the configuration file , We configure it as follows :

<bean id="airConditioner" class="xxx.AirConditionerFactory" factory-method="getInstance"/>
<bean id="car" class="xxx.Car">
    <property name="conditioner" ref="airConditioner"/>
</bean>

about airConditioner This bean Come on ,class It's our own static method factory ,factory-method Is the static method name of the factory . At run time , The container calls the static method of the static method factory class , obtain AirConditioner Example , And then car This bean Inject the instance . Instead of injecting static factory method classes (AirConditionerFactory) Example .

The type of a static factory method class is not necessarily related to the type returned by a static method , It doesn't have to be the same .

in addition , When we generate a concrete implementation , It's possible to rely on some parameters , So how to realize parameter passing ? The specific way is as follows :

public class AirConditionerFactory {
  public static AirConditioner getInstance(String clazz){
    //  Dynamic generation AirConditioner The proxy class implementation of 
  }
}

here , The configuration mode becomes the following :

<bean id="airConditioner" class="xxx.AirConditionerFactory" factory-method="getInstance">
  <constructor-arg>xxx.AirConditioner</constructor-arg>
</bean>
<bean id="car" class="xxx.Car">
    <property name="conditioner" ref="airConditioner"/>
</bean>

What we need to say here is : Passed in configuration file constructor-arg The parameters passed in are static methods , Instead of the parameters of the constructor of the static factory class .

Through a non static factory approach

We can register the call result of static method into container through static factory method , Then we can certainly implement it based on non static factory . The code is as follows :

public class AirConditionerFactory {
  public AirConditioner getInstance(){
    //  Dynamic generation AirConditioner The proxy class implementation of 
  }
}

Because the factory method is not static , So we have to rely on the instance of the factory to get the concrete implementation class , The configuration is as follows :

<bean id="airConditionerFactory" class="xxx.AirConditionerFactory" />
<bean id="airConditioner" factory-bean="airConditionerFactory" factory-method="getInstance"/>
<bean id="car" class="xxx.Car">
    <property name="conditioner" ref="airConditioner"/>
</bean>

You can see , In this way AirConditionerFactory As normal bean Registered in the container . and airConditioner In defining ,factory-bean Property is used to specify instances of factory methods ,factory-method Property is used to specify the factory method name .

When a non static factory method needs to pass parameters , Usage is similar to static factory , It's all used constructor-arg Pass in .

adopt FactoryBean Realization

Like the scene in this article , Or some object instantiation process is too complex , We can do this by implementing org.springframework.beans.factory.FactoryBean Interface to achieve our goal . Although the above two ways can achieve the same effect , But it doesn't feel so elegant .FactoryBean Is the right choice , The source code of the interface is as follows :

public interface FactoryBean {
  Object getObject() throws Exception;
  Class getObjectType();
  boolean isSingleton();
}

among ,getObject() Method returns the FactoryBean Object instances of production .getObjectType It's back to getObject() The type of instance returned by the method , If you can't know the type in advance , Then return to null that will do .isSingleton() Method is used to identify getObject() Method to return the object with singleton The way that exists in the container .

The implementation of this method is as follows :

public class AirConditionerFactory implements FactoryBean {
  public Object getObject() {
    //  Dynamic generation AirConditioner The proxy class implementation of 
  }
  public Class getObjectType() {
    return AirConditioner.class;
  }
  public boolean isSingleton() {
    return true;
  }
}

As for the configuration , It's even simpler , as follows :

<bean id="airConditioner" class="xxx.AirConditionerFactory"/>
<bean id="car" class="xxx.Car">
    <property name="conditioner" ref="airConditioner"/>
</bean>

Just from the configuration file , With the use of ordinary bean It doesn't make any difference , But by definition airConditioner As id Go to the container and get it bean, What we get is FactoryBean The object of production , instead of FactoryBean example .

 So if we just want to get this FactoryBean What about object instances ? Don't worry. , We just need to bean Defined id prefix "&" The prefix can be retrieved from the container FactoryBean An example of itself .( Isn't it a little bit C The smell of address in language , Actually Spring Officially, it's called dereference )

At the end

Actually , stay Spring Inside the container , It's used in many places FactoryBean, Let's list some common FactoryBean The implementation of the :

  • JndiObjectFactoryBean
  • LocalSessionFactoryBean
  • SqlMapClientFactoryBean
  • ProxyFactoryBean
  • TransactionProxyFactoryBean

They hide the complexity of instantiation Bean The details of the , It brings convenience to the upper application . from Spring3.0 Start ,FactoryBean Start supporting generics , That is, the interface declaration is changed to FactoryBean In the form of . and FactoryBean stay AOP And affairs play an irreplaceable role . We'll come into contact with this later ~
 Stop BeanFactory and FactoryBean Stupid is not clear

Ah Hao said
Learned ? Please give me a coffee ~

版权声明
本文为[osc_ vvylzpqs]所创,转载请带上原文链接,感谢
https://chowdera.com/2020/12/202012060705352005.html