В 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…