Spring系统学习 - FactoryBean和基于XML的自动装配

news2024/10/25 10:27:05

Factory Bean

Spring的FactoryBean是一个特殊的Bean,用于创建其他Bean实例。FactoryBean接口定义了一个工厂Bean,该Bean可以用来生成其他Bean的实例。通过实现FactoryBean接口,开发人员可以自定义Bean的创建逻辑,实现更灵活的Bean实例化过程。

FactoryBean是Spring提供的一种整合第三方框架的常用机制。和普通的bean不同,配置一个FactoryBean类型的bean,在获取bean的时候得到的并不是class属性中配置的这个类的对象,而是getObject()方法的返回值。通过这种机制,Spring可以帮我们把复杂组件创建的详细过程和繁琐细节都屏蔽起来,只把最简洁的使用界面展示给我们。

public interface FactoryBean<T> {

	String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
	//返回由FactoryBean创建的Bean实例。
	@Nullable
	T getObject() throws Exception;
	//返回由FactoryBean创建的Bean实例的类型。
	@Nullable
	Class<?> getObjectType();
	//返回由FactoryBean创建的Bean实例是否是单例的。
	default boolean isSingleton() {
		return true;
	}

}

在这里插入图片描述

通过实现FactoryBean接口,开发人员可以自定义Bean的创建过程,实现一些复杂的逻辑,例如对象的缓存、对象的代理等。在Spring中,FactoryBean常用于定制化Bean的创建过程,提供更灵活的Bean管理方式。

案例演示

我们的案例演示将使用上一讲的Spring的bean的生命周期的实例,在我们已经创建好的实例上进行相关处理。

实体类

public class User {
    private Integer id;
    private String username;
    private String password;
    private Integer age;
    public User() {
        System.out.println("生命周期:1、创建对象");
    }
    public User(Integer id, String username, String password, Integer age) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.age = age;
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        System.out.println("生命周期:2、依赖注入");
        this.id = id;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public void initMethod(){
        System.out.println("生命周期:3、初始化");
    }
    public void destroyMethod(){
        System.out.println("生命周期:5、销毁");
    }
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", age=" + age +
                '}';
    }

}

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">


    <!-- 使用init-method属性指定初始化方法 -->
    <!-- 使用destroy-method属性指定销毁方法 -->
    <bean id="userFactory" class="com.miaow.spring.bean.User" init-method="initMethod" destroy-method="destroyMethod">
        <property name="id"  value="257258"></property>
        <property name="age" value="25"></property>
        <property name="password" value="wwafheda"></property>
        <property name="username" value="张老三"></property>
    </bean>

    <bean id="myBeanProcessor" class="com.miaow.spring.process.MyBeanProcessor"></bean>

    <!--    配置bean FactoryBeam-->
    <bean id="userFactoryBean" class="com.miaow.spring.factory.UserFactoryBean"></bean>

</beans>

UserFactoryBean

/**
 * @author HWZ
 * @date 2024年05月11日 10:36
 * @description FactoryBean 是Spring提供的一种整合第三方框架的常用机制,和普通bean不同,配置一个FactoryBean类型的bean,
 *  Spring会调用FactoryBean的getObject()方法来获取一个实例,而不是直接new一个对象。
 *  FactoryBean的getObject()方法返回的是一个实例,而不是一个类。
 *  FactoryBean的getObjectType()方法返回的是一个类,而不是一个实例
 */
public class UserFactoryBean implements FactoryBean<User> {


    @Override
    public User getObject() throws Exception {
        return new User();
    }

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

    @Override
    public boolean isSingleton() {
        return FactoryBean.super.isSingleton();
    }
}

后置处理器

public class MyBeanProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("☆☆☆" + beanName + " = " + bean);
        return bean;
    }


    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("★★★" + beanName + " = " + bean);
        return bean;
    }
}

测试

    //factorty测试
    @Test
    public void FactoryTest(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean-factory.xml");
        User user = (User) context.getBean("userFactory");
        System.out.println(user);
        System.out.println("生命周期:4、通过IOC容器获取bean并使用");
        context.close();
    }

在这里插入图片描述
在这里插入图片描述

基于XML的自动装配

Spring的自动装配是一种通过Spring容器自动连接应用程序中的Bean的方式。当Bean定义了依赖关系时,Spring容器可以自动识别这些依赖关系,并自动将相应的Bean注入到目标Bean中,从而实现Bean之间的自动连接。

目前Spring中提供自动装配的方式分为如下三种:

  • 根据类型自动装配:Spring 容器会自动匹配Bean的类型,将符合类型要求的Bean注入到目标Bean中。
  • 根据名称自动装配:Spring 容器会自动匹配Bean的名称,将符合名称要求的Bean注入到目标Bean中。
  • 构造函数自动装配:Spring 容器会自动识别目标Bean的构造函数,并自动将依赖的Bean注入到构造函数当中。

模拟实现

我们通过一个实例来看一下Spring 的自动装配方式,首先我们创建一个我们常用的开发层。

创建一个控制层

public class UserController {
    private UserService userService;
    public void setUserService(UserService userService) {
        this.userService = userService;
    }
    public void saveUser(){
        userService.saveUser();
    }
}

创建接口UserService

public interface UserService {
	void saveUser();
}

创建Service接口实现层

public class UserServiceImpl implements UserService {
    private UserDao userDao;
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    @Override
    public void saveUser() {
        userDao.saveUser();
    }
}

创建dao层接口

public interface UserDao {
	void saveUser();
}

创建类dao层实现层

public class UserDaoImpl implements UserDao {
    @Override
    public void saveUser() {
        System.out.println("保存成功");
    }
}

根据类型自动装配(byType)

<?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">

<!--    spring IOC的自动装配  根据指定的策略,在IOC容器中匹配某一个bean,自动为指定的bean中所依赖的类类型或接口类
自动装配方式:byType
byType:根据类型匹配IOC容器中的某个兼容类型的bean,为属性自动赋值
若在IOC中,没有任何一个兼容类型的bean能够为属性赋值,则该属性不装配,即值为默认值null
若在IOC中,有多个兼容类型的bean能够为属性赋值,则抛出异常NoUniqueBeanDefinitionException

自动装配方式:byName
byName:将自动装配的属性的属性名,作为bean的id在IOC容器中匹配相对应的bean进行赋值

 -->
    <bean id="userController" class="com.miaow.spring.controller.UserController" autowire="byType"></bean>

<!--    配置 service层-->
    <bean id="userService" class="com.miaow.spring.service.impl.UserServiceImpl" autowire="byType"></bean>

<!--    配置dao层-->
    <bean id="userDao" class="com.miaow.spring.dao.impl.UserDaoImpl"></bean>
</beans>

    //自动装配 通过注解的方式ByType 和 ByName装配
    @Test
    public void AutoWireTest(){
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-user.xml");
        UserController user = (UserController) context.getBean(UserController.class);
        user.saveUser();
    }

在这里插入图片描述

根据名称注入(byName)

    <bean id="userController" class="com.miaow.spring.controller.UserController" autowire="byName"></bean>

    <bean id="userService" class="com.miaow.spring.service.impl.UserServiceImpl" autowire="byName"></bean>

在这里插入图片描述

构造器注入

我们需要创建一个实体类,用来存储我们在XML配置文件中通过构造器注入的相关值。

在Java类中定义相应的构造函数,Spring容器会根据XML配置文件中的<constructor-arg>元素来自动注入参数值。

public class MyBean {

    private int number;
    private AnotherBean anotherBean;

    public MyBean(int number, AnotherBean anotherBean) {
        this.number = number;
        this.anotherBean = anotherBean;
    }



    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
    }

    public AnotherBean getAnotherBean() {
        return anotherBean;
    }

    public void setAnotherBean(AnotherBean anotherBean) {
        this.anotherBean = anotherBean;
    }

    @Override
    public String toString() {
        return "MyBean{" +
                "number=" + number +
                ", anotherBean=" + anotherBean +
                '}';
    }
}
public class AnotherBean {

    private int number;

    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
    }

    @Override
    public String toString() {
        return "AnotherBean{" +
                "number=" + number +
                '}';
    }
}
<!--  构造方法注入  -->

    <bean id="myBean" class="com.miaow.spring.bean.MyBean">
        <constructor-arg value="123" type="int"/>
        <constructor-arg ref="anotherBean"/>
    </bean>

    <bean id="anotherBean" class="com.miaow.spring.bean.AnotherBean"/>
    public void AutoWireTest(){
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-user.xml");
        MyBean myBean = (MyBean) context.getBean("myBean");
        System.out.println(myBean);

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1842541.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

动态竞拍与寄售模式:引领企业增长的新引擎

在当今日新月异的商业环境中&#xff0c;企业的生存与发展不仅需要卓越的产品和服务&#xff0c;更需要紧跟市场脉搏&#xff0c;勇于创新。接下来&#xff0c;我将为您详细介绍一种引领行业新风尚的商业模式——动态竞拍与寄售相结合的模式。这一模式凭借其灵活性和创新性&…

图像处理与视觉感知复习--频率域图像增强图像变换

文章目录 图像变换与信号分解正弦信号与傅里叶级数傅里叶变换离散傅里叶变换(DFT)频率域滤波 图像变换与信号分解 空间域&#xff1a;就是像素域&#xff0c;在空间域的处理是在像素级的处理&#xff0c;如像素级的叠加。 频率域&#xff1a;任何一个波形都可以分解用多个正弦…

【类型转换】C++中char、char*、int、string相互转换函数及string转不同进制数函数

参考资料&#xff1a;cplusplus官方资料strtol 函数用法 总结&#xff1a; 1、这些在做编程题处理输入数据时常用&#xff0c;需要牢记。

【CT】LeetCode手撕—23. 合并 K 个升序链表

目录 题目1- 思路2- 实现⭐23. 合并 K 个升序链表——题解思路 3- ACM 实现 题目 原题连接&#xff1a;23. 合并 K 个升序链表 1- 思路 模式识别&#xff1a;合并 K 个链表 ——> 优先队列 思路 借助优先队列&#xff0c;每次从 k 个链表中&#xff0c;各取一个元素&…

前 OpenAI 首席科学家建「安全超级智能」实验室;Meta 重组元宇宙团队丨 RTE 开发者日报 Vol.228

开发者朋友们大家好&#xff1a; 这里是 「RTE 开发者日报」 &#xff0c;每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE&#xff08;Real-Time Engagement&#xff09; 领域内「有话题的新闻」、「有态度的观点」、「有意思的数据」、「有思考的文章」、「…

Cytoscape之操作界面介绍

Cytoscape 简介 Cytoscape是一个专注于开源网络可视化和分析的软件。软件的核心部分提供了网络显示、布局、查询等方面的基本功能。软件的核心可以通过插件架构进行扩展&#xff0c;这样就能快速地开发出新的功能。 Cytoscape 源自系统生物学&#xff0c;用于将生物分子交互网…

springboot+vue+mysql+mybatis 二手交易平台

springbootvuemysqlmybatis 二手交易平台 相关技术 javaspringbootmybatismysqlvueelementui

Jenkins For Windows编译构建C#项目环境搭建(完整版)

安装Jenkins 下载Windows安装包 官方下载地址 选择稳定版&#xff0c;这里下载的是最新版&#xff0c;如需下载指定版本点击 以前的发行版 配置java环境 下载 java jdk 17 jdk17官方下载链接 这里下载的是msi版本的安装包 安装jdk17 双击运行安装包&#xff0c;一直下…

企业微信内嵌H5项目接入聊天功能

产品需求是,在列表中把符合条件的列表接入聊天功能,以下是详细步骤: 1.引入企业微信 <script src"https://res.wx.qq.com/wwopen/js/jsapi/jweixin-1.0.0.js"></script> 2.获取wx签名(必须要) /*** 获取wx签名**/ export function getWxJsApi(data) {r…

通过Socket通信实现局域网下Amov无人机连接与数据传输

1.局域网下的通信 1.1 局域网 厂家提供的方式是通过Homer图数传工具(硬件)构建的amov局域网实现通信连接. 好处是通信距离足够长,支持150m;坏处是"局部",无法访问互联网. &#xff3b;&#xff29;&#xff2d;&#xff21;&#xff27;&#xff25;&#xff1a;…

使用Python进行音频处理和机器学习

使用Python进行音频处理和机器学习的简介 从高层次上讲&#xff0c;任何机器学习问题都可以分为三种任务&#xff1a;数据任务&#xff08;数据收集&#xff0c;数据清理和特征形成&#xff09;&#xff0c;培训&#xff08;使用数据特征构建机器学习模型&#xff09;和评估&am…

学习新语言方法总结(一)

随着工作时间越长&#xff0c;单一语言越来越难找工作了&#xff0c;需要不停地学习新语言来适应&#xff0c;总结一下自己学习新语言的方法&#xff0c;这次以GO为例&#xff0c;原来主语言是PHP &#xff0c;自学GO 了解语言特性&#xff0c;知道他是干嘛的 go语言&#xff0…

Pikachu靶场--XSS

参考借鉴 Pikachu靶场之XSS漏洞详解_pikachu xss-CSDN博客 一个视频讲清楚XSS跨站脚本&#xff08;CTF教程&#xff0c;Web安全渗透测试入门&#xff09;_bilibili 反射型xss(get) 输入payload&#xff1a;<script>alert(123)</script> 解决一&#xff1a;在URL框内…

安装MySQL5.7版本步骤遇到问题

方法一&#xff1a;下载zip版本&#xff08;我用的这个&#xff09; 参考视频&#xff08;已收藏&#xff09;&#xff1a;windows安装MySQL5.7_哔哩哔哩_bilibili 下载zip压缩包的MySQL的网址&#xff1a;上面这个视频中有哦。 my.ini文件内容如下&#xff1a; [client] p…

动手学自然语言处理:解读大模型背后的核心技术

自从 ChatGPT 横空出世以来&#xff0c;自然语言处理&#xff08;Natural Language Processing&#xff0c;NLP&#xff09; 研究领域就出现了一种消极的声音&#xff0c;认为大模型技术导致 NLP “死了”。在某乎上就有一条热门问答&#xff0c;大家热烈地讨论了这个问题。 有…

部署RAC到单实例ADG(11G)

服务器信息 主库RAC环境信息 主库RAC基本环境 节点1 节点2 OS centos 7.9 centos 7.9 数据库版本 11.2.0.4 11.2.0.4 规格 1C4G 1C4G 主机名 racdb01 racdb02 public ip 192.168.40.135 192.168.40.145 vip 192.168.40.13 192.168.40.14 private ip 192…

Pikachu靶场--文件上传

参考借鉴 Pikachu靶场之文件上传漏洞详解_皮卡丘文件上传漏洞-CSDN博客 文件上传漏洞&#xff1a;pikachu靶场中的文件上传漏洞通关_pikachu文件上传通关-CSDN博客 client check 在桌面新建一个文件夹&#xff0c;准备一个hello.php文件&#xff0c;文件写入如下代码 <?p…

【C++】类和对象(三)构造与析构

文章目录 一、类的6个默认成员函数二、 构造函数干嘛的&#xff1f;语法定义特性综上总结什么是默认构造函数&#xff1f; 三、析构函数干嘛的 &#xff1f;语法定义析构顺序 一、类的6个默认成员函数 如果一个类中什么成员都没有&#xff0c;简称为空类。空类中并不是真的什么…

还在为Android开发找不到图片测试资源发愁吗? DummyImage来助你加速开发

使用 DummyImage 模拟电影应用数据 在开发和测试过程中&#xff0c;模拟数据是不可或缺的工具。它可以帮助我们在没有真实数据的情况下测试应用程序的功能和性能。本文将介绍如何使用 [DummyImage]https://dummyimage.com生成占位符图像来模拟电影应用的数据&#xff0c;并深入…

零拷贝之MMAP:内存映射

零拷贝之MMAP:内存映射 减少cpu拷贝次数 减少时间约为1倍 import java.io.File; import java.io.RandomAccessFile; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel;//零拷贝之MMAP:内存映射 减少cpu拷贝次数 减少时间约为1倍public static void mai…