Spring-bean实例化的方式

前言

什么是bean的实例化?

通常我们使用spring管理java的对象,一般称这个java对象为一个实例化的bean。bean的实例化方式,实际上就是spring创建并管理java对象实例的方式

bean的实例化方式

在Java和Spring框架的上下文中,Bean的实例化是指创建Java对象(Bean)的过程。这个过程涉及到将Java类的定义(即类的字节码)转换成内存中实际可用的对象实例。在Spring框架中,Bean的实例化是Spring容器(也称为IoC容器)管理对象生命周期的一部分,它负责创建、配置、组装和管理这些对象。

Spring容器通过几种不同的方式来实例化Bean,包括但不限于以下几种:

1. 构造方法实例化

  • 方式描述 :通过调用Java Bean类的构造方法来创建对象。默认情况下,Spring会调用Bean的无参数构造方法。如果Bean类中有多个构造方法,可以通过配置指定使用哪个构造方法,或者通过构造方法注入依赖。
  • 应用场景:适用于大多数简单的Bean实例化场景,特别是当Bean的创建不依赖于其他Bean或复杂逻辑时。

2. 静态工厂方法实例化

  • 方式描述 :通过调用静态工厂方法来创建Bean实例。这种方式需要在Spring配置文件中指定工厂类的静态方法。
  • 应用场景:当Bean的创建过程比较复杂,或者Bean的创建依赖于一些静态的、不需要实例化的资源时,可以使用静态工厂方法。

3. 实例工厂方法实例化

  • 方式描述 :通过调用实例工厂的方法来创建Bean实例。这种方式需要首先创建工厂Bean的实例,然后通过该实例的方法来创建目标Bean。
  • 应用场景:当Bean的创建依赖于其他Bean的实例时,或者当Bean的创建过程需要复杂的逻辑处理时,可以使用实例工厂方法。

4. Spring的FactoryBean接口实例化

  • 方式描述 :通过实现Spring的FactoryBean接口来创建Bean实例。FactoryBean接口提供了getObject()方法,Spring容器在调用该方法时返回Bean实例。这种方式允许开发者在Bean的创建过程中进行更复杂的操作,如懒加载、代理创建等。
  • 应用场景:当需要更细粒度的控制Bean的创建过程,或者需要返回Bean的代理对象时,可以使用FactoryBean接口。

5. 反射实例化(非Spring特有)

  • 方式描述:使用Java反射机制来实例化Java Bean对象。通过Class类的newInstance()方法或Constructor类的newInstance()方法可以动态创建对象。
  • 应用场景:在不需要Spring框架的情况下,或者当需要动态地根据类名创建对象时,可以使用反射实例化。

小结

Bean的实例化方式多种多样,每种方式都有其特定的应用场景和优势。在实际开发中,应根据具体需求和开发环境选择合适的实例化方式。同时,随着Spring框架的不断发展,未来还可能出现更多新的实例化方式。

bean的四种实例化方式的案例演示

bean本质上是一个对象,是spring操作类的构造方法创建的(不论这个构造方法是私有还有共有),底层通过反射完成;并且调用的是无参的构造方法。

准备工作

创建一个maven项目,导入spring相关依赖包

XML 复制代码
<dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.2.10.RELEASE</version>
 </dependency>

在resources中配置spring配置文件

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

创建一个UserDao和它的实现类

UserDao

java 复制代码
package com.csx.dao;

public interface UserDao {

    public void say();
}

UserDaoImpl

java 复制代码
package com.csx.dao.impl;

import com.csx.dao.UserDao;

public class UserDaoImpl implements UserDao {
    @Override
    public void say() {
        System.out.println("User实现类执行中...");
    }
}

spring.xml

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

<bean id="userDao" class="com.csx.dao.impl.UserDaoImpl"/>


</beans>

APP

java 复制代码
package com.csx;

import com.csx.dao.UserDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class APP {
    public static void main(String[] args) {
        ApplicationContext context =new ClassPathXmlApplicationContext("spring.xml");
        UserDao userDao = (UserDao) context.getBean("userDao");
        userDao.say();

    }
}

此时采用默认的无参构造来创建UserDaoImpl对象,交给IOC容器管理,如果此时没有无参构造,则创建失败。

创建一个属性,并创建一个构造,导致默认的无参构造失效,则程序运行失败。

注意: 构造方法可以写也可以不写(系统默认给无参构造方法),但是一旦写了构造方法,一定要书写无参的构造方法。

静态工厂实例化bean

使用工厂实例化bean(早期一些项目中使用,目的是为了解耦),即创造对象不直接new,而是通过工厂的方式获取对象

创建工厂类,

注意:工厂中实例化对象的方法是静态的。

UserStaticFactory

java 复制代码
package com.csx.factory;

import com.csx.dao.UserDao;
import com.csx.dao.impl.UserDaoImpl;

public class UserStaticFactory {
    public static UserDao getUserDao(){
        return new UserDaoImpl();
    }
}

工厂类的spring.xml的配置文件设置

spring.xml

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

<!--<bean id="userDao" class="com.csx.dao.impl.UserDaoImpl"/>-->

    <bean id="userDao" class="com.csx.factory.UserStaticFactory" factory-method="getUserDao"/>

</beans>

id:工厂类的别名

class:配置工厂类的全限定名

factory-method:工厂类中的静态方法名

APP

java 复制代码
public class APP {
    public static void main(String[] args) {
        ApplicationContext context =new ClassPathXmlApplicationContext("spring.xml");
        UserDao userDao = (UserDao) context.getBean("userDao");
        userDao.say();

    }
}

实例工厂实例化bean

UserFactory

java 复制代码
package com.csx.factory;

import com.csx.dao.UserDao;
import com.csx.dao.impl.UserDaoImpl;

public class UserFactory {
    public UserDao getUserDao(){
        return new UserDaoImpl();
    }
}

实例工厂中的方式是实例的,不是静态的,因此配置文件中的bean配置也有一些区别

spring.xml

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

<!--<bean id="userDao" class="com.csx.dao.impl.UserDaoImpl"/>-->

<!--    <bean id="userDao" class="com.csx.factory.UserStaticFactory" factory-method="getUserDao"/>-->
    <bean id="userFactory" class="com.csx.factory.UserFactory"/>

    <bean id="userDao" factory-method="getUserDao" factory-bean="userFactory"/>
</beans>

APP

java 复制代码
public class APP {
    public static void main(String[] args) {
        ApplicationContext context =new ClassPathXmlApplicationContext("spring.xml");
        UserDao userDao = (UserDao) context.getBean("userDao");
        userDao.say();

    }
}

实现FactoryBean接口的方式实例化

本质上是对实例工厂实例化bean的一种简化,我们可以看到:

因为实例工厂实例化bean的方式,需要创建一个工厂类对象,但这个对象只在实例化bean的时候使用一次,spring针对这个方式进行了改良。目的是为了简化配置。

UserFactoryBean

创建一个类实现FactoryBean接口,泛型为想要管理的接口类

java 复制代码
public class UserFactoryBean implements FactoryBean<UserDao> {
    @Override
    public UserDao getObject() throws Exception {
        return new UserDaoImpl();
    }

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

spring.xml

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

<!--<bean id="userDao" class="com.csx.dao.impl.UserDaoImpl"/>-->

<!--    <bean id="userDao" class="com.csx.factory.UserStaticFactory" factory-method="getUserDao"/>-->
<!--    <bean id="userFactory" class="com.csx.factory.UserFactory"/>-->

<!--    <bean id="userDao" factory-method="getUserDao" factory-bean="userFactory"/>-->
    <bean id="userDao" class="com.csx.factory.UserFactoryBean"/>
</beans>

此时spring.xml的配置可以直接管理工厂类

APP

java 复制代码
public class APP {
    public static void main(String[] args) {
        ApplicationContext context =new ClassPathXmlApplicationContext("spring.xml");
        UserDao userDao = (UserDao) context.getBean("userDao");
        userDao.say();

    }
}

总结

spring实例化bean的方式,实际上就是spring创建并管理java对象的方式,主要使用反射机制,调用无参构造方法实现。至于静态工厂和实例化工厂创建bean的方式,是为了兼容一些老的项目而采用的方式,目的是为了解耦。

相关推荐
Acrelhuang9 分钟前
安科瑞5G基站直流叠光监控系统-安科瑞黄安南
大数据·数据库·数据仓库·物联网
雷神乐乐9 分钟前
File.separator与File.separatorChar的区别
java·路径分隔符
小刘|13 分钟前
《Java 实现希尔排序:原理剖析与代码详解》
java·算法·排序算法
逊嘘32 分钟前
【Java语言】抽象类与接口
java·开发语言·jvm
morris13140 分钟前
【SpringBoot】Xss的常见攻击方式与防御手段
java·spring boot·xss·csp
十叶知秋1 小时前
【jmeter】jmeter的线程组功能的详细介绍
数据库·jmeter·性能测试
七星静香1 小时前
laravel chunkById 分块查询 使用时的问题
java·前端·laravel
Jacob程序员1 小时前
java导出word文件(手绘)
java·开发语言·word
ZHOUPUYU1 小时前
IntelliJ IDEA超详细下载安装教程(附安装包)
java·ide·intellij-idea
stewie61 小时前
在IDEA中使用Git
java·git