IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Spring中接口 FactoryBean 作用 -> 正文阅读

[Java知识库]Spring中接口 FactoryBean 作用

简述:

Spring 容器中有两种bean :

  • 普通 Bean: Spring 使用反射机制,利用Class 属性来实例化 Bean,放置到容器中
  • 工厂Bean (实现 FactoryBean): 当 Bean 的实例化过程比较复杂是,如果按照传统的方式(XML),则需要提供大量的配置信息, 采用编码的方式创建更加优雅,用户可以通过实现 org.Springframework.bean.factory.FactoryBean 定制 bean 实例化过程

FactoryBean接口对于Spring框架来说占有重要的地位,Spring 自身就提供了很多FactoryBean的实现。它们隐藏了实例化一些复杂bean的细节,给上层应用带来了便利。

从Spring 3.0 开始, FactoryBean开始支持泛型,即接口声明改为FactoryBean 的形式。

Spring 官方文档中对 FactoryBean 介绍:

官方地址:https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-factory-extension-factorybean

You can implement the org.springframework.beans.factory.FactoryBean interface for objects that are themselves factories.

The FactoryBean interface is a point of pluggability into the Spring IoC container’s instantiation logic. If you have complex initialization code that is better expressed in Java as opposed to a (potentially) verbose amount of XML, you can create your own FactoryBean, write the complex initialization inside that class, and then plug your custom FactoryBean into the container.

The FactoryBean interface provides three methods:

  • T getObject(): Returns an instance of the object this factory creates. The instance can possibly be shared, depending on whether this factory returns singletons or prototypes.
  • boolean isSingleton(): Returns true if this FactoryBean returns singletons or false otherwise. The default implementation of this method returns true.
  • Class<?> getObjectType(): Returns the object type returned by the getObject() method or null if the type is not known in advance.

The FactoryBean concept and interface are used in a number of places within the Spring Framework. More than 50 implementations of the FactoryBean interface ship with Spring itself.

When you need to ask a container for an actual FactoryBean instance itself instead of the bean it produces, prefix the bean’s id with the ampersand symbol (&) when calling the getBean() method of the ApplicationContext. So, for a given FactoryBean with an id of myBean, invoking getBean(“myBean”) on the container returns the product of the FactoryBean, whereas invoking getBean(“&myBean”) returns the FactoryBean instance itself.

简述:

  1. Spring 提供了 FactoryBean接口 供我们实现,用于创建复杂的 Bean 对象, 避免复杂的XML配置
  2. FactoryBean 中提供三个 方法:
    • T getObject() : 返回该实现真正创建的 Bean, 非 FactoryBean 本身
    • boolean isSingleton() : 决定 getObject() 是单例 还是 原型(多例),默认是单例
    • Class<?> getObjectType() : 返回 getObject() 对象 Class
  3. Spring 框架内部 也有50多个关于 FactoryBean 的实现;
  4. 获取对象
    • 当获取 FactoryBean 创建的时对象, 可以使用 getBean(“myBean”);
    • 当获取 FactoryBean 对象时,需使用 getBean(“&myBean”)

实战

MySqlSession类:后续交与 MySqlSessionFactory 初始化
package com.lot.learn.spring.factorybean;

import lombok.Data;

@Data
public class MySqlSession {

    private Long id;

    public MySqlSession(Long id) {
        this.id = id;
    }
}

MySqlSessionFactory 实现 FactoryBean, 用于创建 MySqlSession
package com.lot.learn.spring.factorybean;

import lombok.Data;
import org.springframework.beans.factory.FactoryBean;

@Data
public class MySqlSessionFactory implements FactoryBean<MySqlSession> {

    private Long id;

    private Long sessionId;


    @Override
    public MySqlSession getObject() {
        return new MySqlSession(sessionId);
    }

    @Override
    public Class<?> getObjectType() {
        return MySqlSession.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
    
}

spring-factorybean.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <beans>
        <bean id="mySqlSession" class="com.lot.learn.spring.factorybean.MySqlSessionFactory" >
            <property name="id" value= "9999" />
            <property name="sessionId" value= "1" />
        </bean>
    </beans>
</beans>
Maven 配置 dependencies:
<dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.2.9.RELEASE</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.2.9.RELEASE</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>5.2.9.RELEASE</version>
    </dependency>

  </dependencies>
测试类: TestFactoryBean
package factorybean;

import com.lot.learn.spring.factorybean.MySqlSession;
import com.lot.learn.spring.factorybean.MySqlSessionFactory;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath*:spring-factorybean.xml" })
public class TestFactoryBean {


    @Autowired
    private MySqlSessionFactory userFactory1;

    @Autowired
    private MySqlSession mySqlSession1;

    @Autowired
    private ApplicationContext context;

    @Test
    public void test() {
        System.out.println("factory.getId() = " + userFactory1.getId());
        // 我们并没有配置 MySqlSession 仍可以注入
        System.out.println("mySqlSession.getId() = " + mySqlSession1.getId());

        // by Type
        MySqlSession mySqlSession2 = context.getBean(MySqlSession.class);
        MySqlSessionFactory userFactory2 = context.getBean(MySqlSessionFactory.class);

        // by name
        MySqlSession mySqlSession3 = (MySqlSession) context.getBean("mySqlSession");
        MySqlSessionFactory userFactory3 = (MySqlSessionFactory) context.getBean("&mySqlSession");

		// 以下都是 true
        System.out.println("mySqlSession1 == mySqlSession2 :" + (mySqlSession1 == mySqlSession1));
        System.out.println("userFactory1 == userFactory2 :" + (userFactory1 == userFactory1));

        System.out.println("mySqlSession2 == mySqlSession3 :" + (mySqlSession2 == mySqlSession3));
        System.out.println("userFactory2 == userFactory3 :" + (userFactory2 == userFactory3));
    }
}
测试类执行结果:

根据打印结果看, 已经验证上述问题

factory.getId() = 9999
mySqlSession.getId() = 1
mySqlSession1 == mySqlSession2 :true
userFactory1 == userFactory2 :true
mySqlSession2 == mySqlSession3 :true
userFactory2 == userFactory3 :true

代替方案:

现阶段使用 FactoryBean 创建对象的使用习惯越来越少, 有很多其他更方便创建方式:

  • @Configuration和@Bean注解配合,也可以用来创建bean,和FactoryBean的作用基本相同。但是@Bean功能更强大一些,可以支持懒加载,设置作用域等。
  • @Component 也可

End !!!

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-09-13 10:59:34  更:2022-09-13 11:03:16 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 13:01:03-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码