Разница между BeanFactory и FactoryBean в Spring

Java

В Spring есть два интерфейса, BeanFactory и FactoryBean, которые очень похожи по названию и их легко спутать.

Во-первых, BeanFactory

BeanFactoryЭто интерфейс, это спецификация верхнего уровня китайской фабрики Spring, которая является основным интерфейсом контейнера Springioc.getBean(),containsBean()Общие методы управления bean-компонентами и т. д. Контейнер Spring - это его конкретная реализация, такая как:

  • DefaultListableBeanFactory

  • XmlBeanFactory

  • ApplicationContext

Эти классы реализации имеют разные расширения из разных измерений.

1.1. Исходный код

public interface BeanFactory {

	//对FactoryBean的转义定义,因为如果使用bean的名字检索FactoryBean得到的对象是工厂生成的对象,
	//如果需要得到工厂本身,需要转义
	String FACTORY_BEAN_PREFIX = "&";

	//根据bean的名字,获取在IOC容器中得到bean实例
	Object getBean(String name) throws BeansException;

	//根据bean的名字和Class类型来得到bean实例,增加了类型安全验证机制。
	<T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException;

	Object getBean(String name, Object... args) throws BeansException;

	<T> T getBean(Class<T> requiredType) throws BeansException;

	<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;

	//提供对bean的检索,看看是否在IOC容器有这个名字的bean
	boolean containsBean(String name);

	//根据bean名字得到bean实例,并同时判断这个bean是不是单例
	boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

	boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

	boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;

	boolean isTypeMatch(String name, @Nullable Class<?> typeToMatch) throws NoSuchBeanDefinitionException;

	//得到bean实例的Class类型
	@Nullable
	Class<?> getType(String name) throws NoSuchBeanDefinitionException;

	//得到bean的别名,如果根据别名检索,那么其原名也会被检索出来
	String[] getAliases(String name);
}

1.1. Сценарии использования

  • Получить фасоль (Byname или bytype) из контейнера IOC
  • Получение контейнера Ioc, содержащего указанный компонент
  • Определить, является ли компонент синглтоном

2. ФабрикаБин

В первую очередь это фасоль, но не просто фасоль. Это фабричный компонент, который может производить или украшать объекты, аналогичные шаблону factory и шаблону декоратора в шаблоне проектирования. Он может создавать объект, когда это необходимо, и он не ограничен собой, он может возвращать экземпляр любого Бина.

2.1 Исходный код

public interface FactoryBean<T> {

	//从工厂中获取bean
	@Nullable
	T getObject() throws Exception;

	//获取Bean工厂创建的对象的类型
	@Nullable
	Class<?> getObjectType();

	//Bean工厂创建的对象是否是单例模式
	default boolean isSingleton() {
		return true;
	}
}

Как видно из определяемого им интерфейса,FactoryBeanВыступление является обязанностью завода.То есть, если Бин А реализует интерфейс FactoryBean, то А становится фабрикой, а то, что получается по имени А, на самом деле является вызовом фабрикиgetObject()Возвращаемый объект, а не сам A, если вы хотите получить экземпляр самой фабрики A, вам нужно добавить к имени префикс '&'символ.

  • getObject('name') возвращает экземпляр на фабрике
  • getObject('&name') возвращает экземпляр самой фабрики

Обычно бину не нужно реализовывать фабричный шаблон сам по себе, и контейнер Spring играет роль фабрики; но в некоторых случаях сам бин в контейнере является фабрикой, и его роль заключается в создании другого бина. экземпляры. Другие экземпляры bean-компонентов, созданные фабричным bean-компонентом, больше не создаются контейнером Spring, поэтому, в отличие от обычной конфигурации bean-компонента, элемент class больше не требуется.

2.2 Пример

Определение реализации Bean Интерфейс FactoryBean

@Component
public class MyBean implements FactoryBean {
    private String message;
    public MyBean() {
        this.message = "通过构造方法初始化实例";
    }
    @Override
    public Object getObject() throws Exception {
        // 这里并不一定要返回MyBean自身的实例,可以是其他任何对象的实例。
        //如return new Student()...
        return new MyBean("通过FactoryBean.getObject()创建实例");
    }
    @Override
    public Class<?> getObjectType() {
        return MyBean.class;
    }
    public String getMessage() {
        return message;
    }
}

MyBean реализует два метода интерфейса FactoryBean.getObject() может возвращать экземпляр любого объекта.Здесь тест возвращает экземпляр самого MyBean и присваивает значение полю сообщения перед возвратом. При этом сообщению также присваивается значение в методе построения. Затем в тестовом коде сначала получите экземпляр Bean по имени, распечатайте содержимое сообщения, а затем передайте&+名称Получите экземпляр и распечатайте содержимое сообщения.

@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestApplication.class)
public class FactoryBeanTest {
    @Autowired
    private ApplicationContext context;
    @Test
    public void test() {
        MyBean myBean1 = (MyBean) context.getBean("myBean");
        System.out.println("myBean1 = " + myBean1.getMessage());
        MyBean myBean2 = (MyBean) context.getBean("&myBean");
        System.out.println("myBean2 = " + myBean2.getMessage());
        System.out.println("myBean1.equals(myBean2) = " + myBean1.equals(myBean2));
    }
}
myBean1 = 通过FactoryBean.getObject()初始化实例
myBean2 = 通过构造方法初始化实例
myBean1.equals(myBean2) = false

2.3 Сценарии использования

Сказав так много, почемуFactoryBeanЕсть ли у этой штуки какой-то специфический эффект?
FactoryBean весной наиболее типичное применение используетсяСоздайте объект агента АОП.

Мы знаем, что АОП на самом деле создает прокси-объект Spring во время выполнения, а это означает, что этот объект создается нами во время выполнения, а не определяется в начале, что соответствует шаблону фабричного метода. Более наглядно, прокси-объект АОП создает прокси-объект во время выполнения с помощью механизма отражения Java и вплетает соответствующий метод в целевой метод прокси-объекта в соответствии с бизнес-требованиями. Этот объект в Spring -ProxyFactoryBean.

Таким образом, FactoryBean предоставляет нам более гибкий способ создания экземпляров bean-компонентов, и мы можем создавать более сложные экземпляры Bean-компонентов с помощью FactoryBean.

3. Разница

  • Оба они фабрика, ноFactoryBeanПо сути, это Bean, также принадлежащийBeanFactoryуправлять
  • BeanFactoryэто интерфейс верхнего уровня контейнера Spring,FactoryBeanБольше похоже на определяемый пользователем заводской интерфейс.

Суммировать

BeanFactoryиFactoryBeanРазницу действительно легко спутать, а зазубривание недопустимо, лучше всего понимать ее на уровне исходного кода и в среде spring.

Ссылаться на:
Ооо, ооо на .cn blog .com/с Рэймондом/страх...
блог woo woo woo.cn on.com/returning 18/afraid/1…