SSM-Spring-IOC/DI对应的配置开发

news2025/1/4 6:57:13

目录

一、IOC 控制反转

1.什么是控制反转呢

2. Spring和IOC之间的关系是什么呢?

3.IOC容器的作用以及内部存放的是什么?

4.当IOC容器中创建好service和dao对象后,程序能正确执行么?  

5.Spring 容器管理什么内容?

6.如何将需要管理的对象交给 Spring 的 IOC 容器?

7.如何获取 Spring 的 IOC 容器?

8.如何从 Spring 容器中获取 Bean 对象?

9.使用 Spring 需要导入哪些依赖?

二、DI

三、bean基础配置

1.bean标签的功能、使用方式以及id和class属性的作用

 2.bean的name属性

3.bean作用范围scope配置

1.为什么Spring中的Bean默认是单例的?

2.Bean是单例的,会不会产生线程安全问题?

3.哪些Bean对象适合交给Spring容器管理?

4.哪些Bean对象不适合交给Spring容器管理?

5.总结

4.bean实例化

1. 构造方法实例化

 2. 静态工厂实例化

 3.实例工厂实例化

5.FactoryBean的使用

6.bean的生命周期

1. 为啥Bean的init方法执行了,但是destroy方法却未执行?

2.如何解决?

2.1 使用close方法关闭容器

2.2 使用registerShutdownHook方法

3.Bean生命周期中的重要阶段

        初始化容器

        使用Bean

        关闭/销毁容器

四、DI依赖注入的方式

1.setter注入

注入引用数据类型

注入简单数据类型

2. 构造器注入

注入引用数据类型

注入简单数据类型

3. 自动装配

4.集合注入

五、IOC/DI配置管理第三方bean

1 数据源对象管理

1-引依赖 

2-配置第三方bean

3-从IOC容器中获取对应的bean对象

2 加载properties文件

1 步骤

2 读取(注入)单个属性

3 当有多个properties配置文件需要被加载

六、核心容器

1 容器的创建方式

2 Bean的三种获取方式

3 容器类层次结构

 4 BeanFactory

5 总结

1-容器相关

2-bean相关

3-依赖注入相关


Spring指的是Spring Framework,Spring Framework是Spring生态圈中最基础的项目,是其他项目的根基。

Spring核心概念部分中主要包含IOC/DI、IOC容器和Bean

一、IOC 控制反转

1.什么是控制反转呢

控制反转(IOC)是一种设计思想,就是原本在程序中需要手动创建对象,现在交由Spring管理创建。比如说,原本我们要在A类中调用B类的方法,就要直接在A中new出B类对象,然后调用B类中的方法,虽然能实现效果,不过存在一个问题,更改需求会对源代码进行修改,这不是好的解决方法。现在创建B对象就交给了Spring,在Spring中,B类对象被看成Bean对象(Spring中类就是Bean),这个Bean对象由spring容器进行创建和管理,这样的话A对象获取B对象中的方法,由主动new,变成被动等Spring创建。主动变被动,就可以理解成控制反转,这样大大降低了耦合,Spring中全都用这种思想,即依赖类不由程序员实例化,而是通过Spring容器帮我们new指定的实例并且将实例注入到需要该对象的类中,而 依赖注入(DI) 是实现这种思想的具体手段,Spring通过DI(依赖注入)实现IOC(控制反转)。

2. Spring和IOC之间的关系是什么呢?

Spring技术对IOC思想进行了实现

Spring提供了一个容器,称为IOC容器,用来充当IOC思想中的"外部"

IOC思想中的别人[外部]指的就是Spring的IOC容器

3.IOC容器的作用以及内部存放的是什么?

IOC容器负责对象的创建、初始化等一系列工作,其中包含了数据层和业务层的类对象

被创建或被管理的对象在IOC容器中统称为Bean

IOC容器中放的就是一个个的Bean对象

4.当IOC容器中创建好service和dao对象后,程序能正确执行么?  

当 IOC 容器中已经创建了 servicedao 对象后,程序仍然无法正常运行,因为 service 对象的正常运行依赖于 dao 对象。但此时,尽管 IOC 容器中已经存在这两个对象,它们之间并没有建立任何联系。

要让 service 对象能够正常运行,就需要将 dao 对象注入到 service 对象中,建立两者之间的依赖关系。这种在容器中为对象之间建立依赖关系的方式,称为 依赖注入(DI,Dependency Injection)。通过 DI,IOC 容器会自动将 dao 对象赋值到 service 的属性中,从而使得 service 可以调用 dao 提供的功能。

5.Spring 容器管理什么内容?

 Spring 使用 IOC 容器来管理项目中所使用到的类对象,比如 ServiceDao 等。这些对象在项目中被称为 Bean,它们的创建、初始化、销毁及依赖关系都由容器管理。

6.如何将需要管理的对象交给 Spring 的 IOC 容器?

可以通过 配置文件注解 的方式将对象告知 IOC 容器:

配置文件方式:在 applicationContext.xml 等配置文件中定义 Bean 的信息。

<?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标签标示配置bean
   id属性标示给bean起名字
   class属性表示给bean定义类型
 -->
 <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
    <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl"/>
 
</beans>

bean定义时id属性在同一个上下文中(配置文件)不能重复 

注解方式:使用如 @Component@Service@Repository 等注解标注类,并配合 @ComponentScan 扫描包路径。

7.如何获取 Spring 的 IOC 容器?

Spring 提供了相应的接口(如 ApplicationContext),通过这些接口可以获取到 IOC 容器实例。

常见的实现类有:ClassPathXmlApplicationContextAnnotationConfigApplicationContext

public class App {
    public static void main(String[] args) {
        //获取IOC容器
 ApplicationContext ctx = new 
ClassPathXmlApplicationContext("applicationContext.xml"); 
   }
}

8.如何从 Spring 容器中获取 Bean 对象?

获取 IOC 容器实例后,可以通过 getBean() 方法获取 Bean 对象

通过 Bean 的名称 获取:context.getBean("beanName")

通过 Bean 的类型 获取:context.getBean(BeanClass.class)

9.使用 Spring 需要导入哪些依赖

使用 Maven 管理项目时,需要在 pom.xml 中添加 Spring 的相关依赖。最基本的依赖包括:

spring-core: 提供 Spring 的核心功能。

spring-context: 提供 IOC 容器的功能。

spring-beans: 提供对 Bean 的管理和依赖注入功能。

如果需要数据库操作或 Web 开发,还需要加入对应模块(如 spring-jdbcspring-web 等)。

二、DI

IOC入门已经完成,但是在BookServiceImpl的类中依然存在BookDaoImpl对象的 new操作,它们之间的耦合度还是比较高,这块该如何解决,就需要用到下面的DI:依赖注入。

1. 不用手动new对象了

2. 在调用者类中 为被调用对象提供setter方法

public class BookServiceImpl implements BookService {
    //删除业务层中使用new的方式创建的dao对象
    private BookDao bookDao;
 
    public void save() {
        System.out.println("book service save ...");
        bookDao.save();
   }
    //提供对应的set方法
    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
   }
}

3. 修改配置文件中添加依赖注入的配置

<?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标签标示配置bean
   id属性标示给bean起名字
   class属性表示给bean定义类型
 -->
    <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
 
    <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
        <!--配置server与dao的关系-->
        <!--property标签表示配置当前bean的属性
       name属性表示配置哪一个具体的属性
       ref属性表示参照哪一个bean
 -->
        <property name="bookDao" ref="bookDao"/>
    </bean>
 
</beans>

注意:配置中的两个bookDao的含义是不一样的

name="bookDao"中bookDao的作用是让Spring的IOC容器在获取到名称后,将首字母大写,前 面加set找对应的setBookDao()方法进行对象注入

ref="bookDao"中bookDao的作用是让Spring能在IOC容器中找到id为bookDao的Bean对象给 bookService进行注入

三、bean基础配置

1.bean标签的功能、使用方式以及id和class属性的作用

 2.bean的name属性

 打开配置文件applicationContext.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">
 
    <!--name:为bean指定别名,别名可以有多个,使用逗号,分号,空格进行分隔-->
    <bean id="bookService" name="service service4 bookEbi" 
class="com.itheima.service.impl.BookServiceImpl">
        <property name="bookDao" ref="bookDao"/>
    </bean>
 
    <!--scope:为bean设置作用范围,可选值为单例singloton,非单例prototype-->
    <bean id="bookDao" name="dao" class="com.itheima.dao.impl.BookDaoImpl"/>
</beans>

3.bean作用范围scope配置

 

使用bean的scope属性可以控制bean的创建是否为单例:

singleton默认为单例

prototype为非单例

1.为什么Spring中的Bean默认是单例的?

Spring中的Bean默认是单例的,这意味着在IOC容器中同一个Bean类只有一个实例。这种设计的主要目的是为了优化系统性能,避免频繁创建和销毁对象所带来的资源浪费。通过实现对象复用,单例模式大大提高了性能和资源利用率,适合大多数业务场景。

2.Bean是单例的,会不会产生线程安全问题?

单例Bean在多线程环境下,可能会存在线程安全问题。是否存在问题取决于Bean的状态特性:

  1. 有状态对象:如果Bean中包含成员变量用来存储数据,那么在多线程共享同一个Bean实例时,不同线程可能会修改这些成员变量的值,从而导致线程安全问题。

  2. 无状态对象:如果Bean中没有成员变量,且仅通过方法调用进行操作(方法中使用局部变量),则是线程安全的。因为局部变量是线程私有的,在方法调用完成后会被销毁,因此不存在安全隐患。

在实际开发中,建议对无状态的业务逻辑使用单例模式,而对于有状态的对象,可以考虑通过Spring的其他作用域(如prototype)来实现每次请求生成一个新对象。

3.哪些Bean对象适合交给Spring容器管理?

适合交给Spring容器管理的Bean对象主要包括以下几类:

  1. 表现层对象:如控制器类(Controller),用于处理用户的请求并返回相应的结果。

  2. 业务层对象:如服务类(Service),封装了核心的业务逻辑。

  3. 数据层对象:如数据访问对象(DAO),负责与数据库进行交互。

  4. 工具类对象:如日志工具、加密工具等通用工具类,这类对象通常无状态,适合单例管理。

通过交给Spring容器管理,这些对象的生命周期可以被Spring很好地控制,并通过依赖注入(DI)实现对象之间的协作关系。

4.哪些Bean对象不适合交给Spring容器管理?

并不是所有对象都适合交由Spring容器管理,以下几类对象不适合:

  1. 具有强状态性的对象:例如使用ThreadLocal存储线程相关数据的对象,每个线程需要独立的实例,不适合单例管理。

  2. 短生命周期的临时对象:例如临时使用的工具类对象、结果集对象等,这些对象通常是瞬时的,频繁创建和销毁。如果交给容器管理,反而增加了开销。

  3. 需要动态创建的对象:例如通过第三方库动态生成的对象,或需要复杂初始化逻辑的对象,这类对象通常需要灵活控制生命周期。

  4. 底层资源相关的对象:如文件I/O、数据库连接、网络Socket等,这些对象通常需要手动管理其生命周期,以确保资源的及时释放。

 5.总结

4.bean实例化

容器中是如何来创建对象的呢 就需要研究下bean的实例化过程

bean本质上就是对象,对象在new的时候会使用构造方法完成,那创建bean也是使用构造方法完成的。

spring中bean的三种创建方式:

1. 构造方法实例化

通过直接调用类的构造方法来创建Bean对象。这是Spring中最常用的实例化方式,也是默认方式。

适合需要使用类的默认构造方法或无参构造方法来创建对象的场景。

 2. 静态工厂实例化

通过调用静态工厂类的某个静态方法来创建Bean对象。

(1)创建一个工厂类OrderDaoFactory并提供一个静态方法

//静态工厂创建对象
public class OrderDaoFactory {
    public static OrderDao getOrderDao(){
        return new OrderDaoImpl();
   }
}

(2)在spring的配置文件application.properties中添加以下内容:

<bean id="orderDao" class="com.itheima.factory.OrderDaoFactory" factorymethod="getOrderDao"/>

class:工厂类的类全名

factory-mehod:具体工厂类中创建对象的方法名

静态方法属于类本身,无需通过实例化工厂类来调用。这减少了不必要的对象创建,节省内存和资源。

3.实例工厂实例化

通过先创建工厂类的实例,再调用实例工厂的某个方法来创建Bean对象。

在Spring的XML配置中,通过factory-bean属性指定工厂Bean的名称,通过factory-method属性指定实例方法。

工厂类

public class BeanFactory {
    public UserService createUserService() {
        return new UserService();
    }
}

Spring配置

<!-- 配置工厂类 -->
<bean id="beanFactory" class="com.example.factory.BeanFactory" />
<!-- 通过工厂类实例方法创建Bean -->
<bean id="userService" factory-bean="beanFactory" factory-method="createUserService" />

实例化工厂运行的顺序是: 创建实例化工厂对象

调用对象中的方法来创建bean

factory-bean:工厂的实例对象

factory-method:工厂对象中的具体创建对象的方法名

 5.FactoryBean的使用

步骤:

(1)创建一个UserDaoFactoryBean的类,实现FactoryBean接口,重写接口的方法

public class UserDaoFactoryBean implements FactoryBean<UserDao> {
    //代替原始实例工厂中创建对象的方法
    public UserDao getObject() throws Exception {
        return new UserDaoImpl();
   }
    //返回所创建类的Class对象
    public Class<?> getObjectType() {
        return UserDao.class;
   }
}

(2)在Spring的配置文件中进行配置

<bean id="userDao" class="com.itheima.factory.UserDaoFactoryBean"/>

 FactoryBean接口其实会有三个方法

T getObject() throws Exception;
 
Class<?> getObjectType();
 
default boolean isSingleton() {
 return true;
}

方法一:getObject(),被重写后,在方法中进行对象的创建并返回

方法二:getObjectType(),被重写后,主要返回的是被创建类的Class对象

方法三:没有被重写,因为它已经给了默认值,从方法名中可以看出其作用是设置对象是否为单例,默认true

那如果想改成多例具体如何实现? 只需要将isSingleton()方法进行重写,修改返回为false,一般情况下我们都会采用单例,也就是采用默认即可。 所以isSingleton()方法一般不需要进行重写。

注意:

构造方法在类中默认会提供,但是如果重写了构造方法,默认的就会消失,在使用的过程中需要注意,如果需要重写构造方法,最好把默认的构造方法也重写下。  

6.bean的生命周期

1. 为啥Bean的init方法执行了,但是destroy方法却未执行?

Spring的IOC容器运行在JVM中,当运行main方法后,JVM启动,Spring加载配置文件生成IOC容器。随后,从容器中获取Bean对象,执行相关方法。

然而,main方法执行完毕后,JVM直接退出,Spring的IOC容器没有来得及销毁其管理的Bean对象,因此对应的destroy方法未被调用。

2.如何解决?

Spring提供了两种方式解决destroy方法未被执行的问题: 

2.1 使用close方法关闭容器

默认情况下,ApplicationContext接口并没有提供close方法,因此需要使用ClassPathXmlApplicationContext类(ApplicationContext的实现类),通过调用close方法手动关闭容器。

ClassPathXmlApplicationContext ctx = 
    new ClassPathXmlApplicationContext("applicationContext.xml");
ctx.close();  // 关闭容器,触发Bean的销毁方法
<bean id="bookDao" class="com.example.dao.impl.BookDaoImpl" 
      init-method="init" destroy-method="destroy" />
2.2 使用registerShutdownHook方法

 提前注册一个钩子函数,让JVM在退出之前自动调用这个回调函数来关闭容器。

ClassPathXmlApplicationContext ctx = 
    new ClassPathXmlApplicationContext("applicationContext.xml");
ctx.registerShutdownHook();  // 注册关闭钩子

无论是手动调用close(),还是使用registerShutdownHook(),都可以正常触发Bean的destroy方法。

相同点:这两种都能用来关闭容器

不同点:close()是在调用的时候关闭,registerShutdownHook()是在JVM退出前调用关闭。  

Spring提供了两个接口来完成生命周期的控制,好处是可以不用再进行配置init-method和 destroy-method

public class BookServiceImpl implements BookService, InitializingBean, 
DisposableBean {
    private BookDao bookDao;
    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
   }
public void save() {
        System.out.println("book service save ...");
        bookDao.save(); 
   }
    public void destroy() throws Exception {
        System.out.println("service destroy");
   }
    public void afterPropertiesSet() throws Exception {
        System.out.println("service init");
   }
}

对于InitializingBean接口中的afterPropertiesSet方法,翻译过来为属性设置之后。

对于BookServiceImpl来说,bookDao是它的一个属性

setBookDao方法是Spring的IOC容器为其注入属性的方法

3.Bean生命周期中的重要阶段

  1. 初始化容器

    • 创建对象:在容器中为Bean分配内存。
    • 执行构造方法:调用Bean的无参构造方法,完成对象的创建。
    • 属性注入:使用set方法将依赖注入到Bean中。
    • 执行初始化方法:调用Bean的初始化方法,完成对象的初始化操作。
  2. 使用Bean

    • 调用Bean的业务逻辑方法,完成具体的业务操作。
  3. 关闭/销毁容器

    • 执行销毁方法:当容器关闭时,调用Bean的销毁方法,释放资源。

四、DI依赖注入的方式

1.setter注入

注入引用数据类型

在bean中定义引用类型属性,并提供可访问的set方法

public class BookServiceImpl implements BookService {
    private BookDao bookDao;
    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
   }
}

配置中使用property标签ref属性注入引用类型对象  

<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
 <property name="bookDao" ref="bookDao"/>
</bean>
 
<bean id="bookDao" class="com.itheima.dao.imipl.BookDaoImpl"/>

注入简单数据类型

1. 在BookDaoImpl类中声明对应的简单数据类型的属性,并提供对应的setter方法

public class BookDaoImpl implements BookDao {
 
    private String databaseName;
    private int connectionNum;
 
    public void setConnectionNum(int connectionNum) {
        this.connectionNum = connectionNum;
   }
 
    public void setDatabaseName(String databaseName) {
        this.databaseName = databaseName;
   }
 
    public void save() {
        System.out.println("book dao save 
..."+databaseName+","+connectionNum);
   }
}

 2. 在applicationContext.xml配置文件中使用property标签注入

<?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="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
        <property name="databaseName" value="mysql"/>
     <property name="connectionNum" value="10"/>
    </bean>
    <bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
    <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
        <property name="bookDao" ref="bookDao"/>
        <property name="userDao" ref="userDao"/>
    </bean>

对于引用数据类型使用的是<property name=" " ref=" "/>

对于简单数据类型使用的是<property name=" " value=" "/>

2. 构造器注入

注入引用数据类型

(1)在BookServiceImpl类中将bookDao的setter方法删除掉,并添加带有bookDao参数的构造方法

public class BookServiceImpl implements BookService{
    private BookDao bookDao;
 
    public BookServiceImpl(BookDao bookDao) {
        this.bookDao = bookDao;
   }
 
    public void save() {
        System.out.println("book service save ...");
        bookDao.save();
   }
}

(2)配置文件中进行配置构造方式注入

<?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="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
    <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
        <constructor-arg name="bookDao" ref="bookDao"/>
    </bean>
</beans>

name属性对应的值为构造函数中方法形参的参数名,必须要保持一致

ref属性指向的是spring的IOC容器中其他bean对象。

注入简单数据类型

public class BookDaoImpl implements BookDao {
    private String databaseName;
    private int connectionNum;
 
    public BookDaoImpl(String databaseName, int connectionNum) {
        this.databaseName = databaseName;
        this.connectionNum = connectionNum;
   }
 
    public void save() {
        System.out.println("book dao save 
..."+databaseName+","+connectionNum);
   }
}
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
        <constructor-arg name="databaseName" value="mysql"/>
        <constructor-arg name="connectionNum" value="666"/>
    </bean>
    <bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
    <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
        <constructor-arg name="bookDao" ref="bookDao"/>
        <constructor-arg name="userDao" ref="userDao"/>
    </bean>

实际开发过程中还要根据实际情况分析,如果受控对象没有提供setter方法就必须使用构造器注入

 

 引用数据类型

3. 自动装配

自动装配只需要修改applicationContext.xml配置文件即可:

(1)将标签删除

(2)在标签中添加autowire属性

<?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 class="com.itheima.dao.impl.BookDaoImpl"/>
    <!--autowire属性:开启自动装配,通常使用按类型装配-->
    <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl" 
autowire="byType"/>
 
</beans>

一个类型在IOC中有多个对象,还想要注入成功,这个时候就需要按照名称注入

<?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 class="com.itheima.dao.impl.BookDaoImpl"/>
    <!--autowire属性:开启自动装配,通常使用按类型装配-->
    <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl" 
autowire="byName"/>
 
</beans>

1. 自动装配用于引用类型依赖注入,不能对简单类型进行操作

2. 使用按类型装配时(byType)必须保障容器中相同类型的bean唯一,推荐使用

3. 使用按名称装配时(byName)必须保障容器中具有指定名称的bean,因变量名与配置耦合,不推 荐使用

4. 自动装配优先级低于setter注入与构造器注入,同时出现时自动装配配置失效

4.集合注入

还有一种数据类型集合,集合中既可以装简单数据类型也可以装引用数据类型

1. 注入数组类型数据

在 Spring 配置文件中,可以通过 <property> 标签结合 <array> 子标签为 Bean 注入数组类型的数据。数组类型的数据通常用于注入一组固定长度的值。

<property name="array">
    <array>
        <value>100</value>
        <value>200</value>
        <value>300</value>
    </array>
</property>

2. 注入 List 类型数据

 Spring 提供了 <list> 标签用于注入 List 类型的数据。List 是一种有序的集合,支持重复元素。

<property name="list">
    <list>
        <value>itcast</value>
        <value>itheima</value>
        <value>boxuegu</value>
        <value>chuanzhihui</value>
    </list>
</property>

 3. 注入 Set 类型数据

<property name="set">
    <set>
        <value>itcast</value>
        <value>itheima</value>
        <value>boxuegu</value>
        <value>boxuegu</value> <!-- 重复值将被忽略 -->
    </set>
</property>

4. 注入 Map 类型数据

<property name="map">
    <map>
        <entry key="name" value="itheima"/>
        <entry key="age" value="30"/>
        <entry key="address" value="Beijing"/>
    </map>
</property>

5. 注入 Properties 类型数据

<property name="properties">
    <props>
        <prop key="database">MySQL</prop>
        <prop key="username">root</prop>
        <prop key="password">123456</prop>
    </props>
</property>

property标签表示setter方式注入,构造方式注入constructor-arg标签内部也可以写 、、、、标签 List的底层也是通过数组实现的,所以和标签是可以混用 集合中要添加引用类型,只需要把标签改成标签,这种方式用的比较少。

五、IOC/DI配置管理第三方bean

有需求让我们去管理第三方jar包中的类

1 数据源对象管理

以数据源Druid(德鲁伊)和C3P0 为例

1-引依赖 

2-配置第三方bean

在applicationContext.xml配置文件中添加DruidDataSource的配置

<?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">
 <!--管理DruidDataSource对象-->
    <bean class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/spring_db"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>
</beans>

3-从IOC容器中获取对应的bean对象

public class App {
    public static void main(String[] args) {
       ApplicationContext ctx = new 
ClassPathXmlApplicationContext("applicationContext.xml");
       DataSource dataSource = (DataSource) ctx.getBean("dataSource");
       System.out.println(dataSource);
   }
}

如果对于新的技术不知道具体的坐标哪里查找的话 直接百度搜索或者 从mvn仓库https://mvnrepository.com/中进行搜索

Druid和C3P0在没有导入mysql驱动包的前提下,一个没报错一个报错,说明Druid在初始化的时候没有去加载驱动,而C3P0刚好相反 Druid程序运行虽然没有报错,但是当调用DruidDataSource的getConnection()方法获取连 接的时候,也会报找不到驱动类的错误

2 加载properties文件

1 步骤

需求:将数据库连接四要素提取到properties配置文件,spring来加载配置信息并使用这些信息来完成属性注入。

1.在resources下创建一个jdbc.properties(文件的名称可以任意)

2.将数据库连接四要素配置到配置文件中

3.在Spring的配置文件中加载properties文件

4.使用加载到的值实现属性注入

1-准备properties配置文件

resources下创建一个jdbc.properties文件,并添加对应的属性键值对

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/spring_db
jdbc.username=root
jdbc.password=root

2-开启context命名空间

在applicationContext.xml中开context命名空间

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

3-加载properties配置文件

在配置文件中使用context命名空间下的标签来加载properties配置文件

<context:property-placeholder location="jdbc.properties"/>

4-完成属性注入

 使用${key}来读取properties配置文件中的内容并完成属性注入

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

   
    <context:property-placeholder location="jdbc.properties"/>
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
</beans>

2 读取(注入)单个属性

<context:property-placeholder location="jdbc.properties"/>
    
    <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
        <property name="name" value="${jdbc.driver}"/>
    </bean>

问题一:键值对的key为username引发的问题

环境变量的值会被优先加载

解决方法:

<context:property-placeholder location="jdbc.properties" systemproperties-mode="NEVER"/>

system-properties-mode:设置为NEVER,表示不加载系统属性

3 当有多个properties配置文件需要被加载

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

   <!--方式一 -->
<context:property-placeholder 
location="jdbc.properties,jdbc2.properties" system-propertiesmode="NEVER"/>

   <!--方式二-->
    <context:property-placeholder location="*.properties" systemproperties-mode="NEVER"/>

   <!--方式三 -->
    <context:property-placeholder location="classpath:*.properties" 
system-properties-mode="NEVER"/>
    <!--方式四-->
    <context:property-placeholder location="classpath*:*.properties" 
system-properties-mode="NEVER"/>
</beans> 

方式一:可以实现,如果配置文件多的话,每个都需要配置

方式二: *.properties代表所有以properties结尾的文件都会被加载,可以解决方式一的问题,但是不标准

方式三:标准的写法,classpath:代表的是从根路径下开始查找,但是只能查询当前项目的根路径

方式四:不仅可以加载当前项目还可以加载当前项目所依赖的所有项目的根路径下的properties配置文件

六、核心容器

IOC容器中的核心容器

1 容器的创建方式

(1)类路径下的XML配置文件

ApplicationContext ctx = new 
ClassPathXmlApplicationContext("applicationContext.xml");

(2)文件系统下的XML配置文件

ApplicationContext ctx = new 
FileSystemXmlApplicationContext("applicationContext.xml");

这种方式是从项目路径下开始查找applicationContext.xml配置文件的,所以要写绝对路径

2 Bean的三种获取方式

方式一
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
这种方式存在的问题是每次获取的时候都需要进行类型转换

方式二
BookDao bookDao = ctx.getBean("bookDao",BookDao.class);
这种方式可以解决类型强转问题,但是参数又多加了一个

方式三
BookDao bookDao = ctx.getBean(BookDao.class);
这种方式就类似我们之前所学习依赖注入中的按类型注入。必须要确保IOC容器中该类型对应的bean
对象只能有一个。

3 容器类层次结构

不想看、只需要知晓容器的最上级的父接口为BeanFactory即可

 4 BeanFactory

使用BeanFactory来创建IOC容器的具体实现方式为:

public class AppForBeanFactory {
    public static void main(String[] args) {
        Resource resources = new ClassPathResource("applicationContext.xml");
        BeanFactory bf = new XmlBeanFactory(resources);
        BookDao bookDao = bf.getBean(BookDao.class);
        bookDao.save();
   }
}

BeanFactory和ApplicationContext之间的区别

BeanFactory是延迟加载,只有在获取bean对象的时候才会去创建

ApplicationContext是立即加载,容器加载的时候就会创建bean对象

ApplicationContext要想成为延迟加载,只需要按照如下方式进行配置:

<?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="bookDao" class="com.itheima.dao.impl.BookDaoImpl"  lazyinit="true"/>
</beans>

5 总结

1-容器相关

BeanFactory是IoC容器的顶层接口,初始化BeanFactory对象时,加载的bean延迟加载

ApplicationContext接口是Spring容器的核心接口,初始化时bean立即加载

ApplicationContext接口提供基础的bean操作相关方法,通过其他接口扩展其功能

ApplicationContext接口常用初始化类

ClassPathXmlApplicationContext(常用)

FileSystemXmlApplicationContext

2-bean相关

3-依赖注入相关

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

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

相关文章

docker中使用nginx

宿主机和docker中nginx做映射 宿主机中nginx 映射目录 /root/myDockerData/devnginx 在容器中相关位置分别是&#xff1a; 配置文件位置&#xff1a;/etc/nginx/ 日志位置&#xff1a;/var/log/nginx/ 项目位置&#xff1a;/usr/share/nginx/html 如下配置启动命令行&#x…

Rocky Linux下安装meld

背景介绍&#xff1a; meld是一款Linux系统下的用于 文件夹和文件的比对软件&#xff0c;非常常用&#xff1b; 故障现象&#xff1a; 输入安装命令后&#xff0c;sudo yum install meld&#xff0c;报错。 12-31 22:12:17 ~]$ sudo yum install meld Last metadata expirat…

Python中PDF转Word的技术

Python PDF转Word技术概述 在日常办公和数据处理中&#xff0c;经常需要将PDF文档转换为Word文档&#xff0c;以便进行编辑、修改或格式调整。Python作为一种强大的编程语言&#xff0c;提供了多种库和工具来实现这一功能。以下是对Python中PDF转Word技术的详细介绍。 一、技…

混合并行训练框架性能对比

混合并行训练框架性能对比 1. 框架类型 DeepSpeed、Megatron - LM、Colossal - AI、SageMaker、Merak、FasterMoE、Tutel、Whale、Alpa、DAPPLE、Mesh - TensorFlow 2. 可用并行性(Available parallelisms) DNN framework(深度神经网络框架)DP(数据并行,Data Parallelis…

python24-常用的第三方库02:openpyxl模块、pdfplumber模块

一、openpyxl模块 openpyxl 是一个用于读取和写入 Excel 2010 xlsx/xlsm/xltx/xltm 文件的 Python 库。 它允许你以编程方式操作 Excel 文件&#xff0c;包括创建新的工作簿、修改现有的工作簿、添加或删除工作表、读写单元格数据等。 1-1、安装openpyxl模块 验证&#xff1a…

npm ERR! ECONNRESET 解决方法

问题&#xff1a;npm 命令遇到的错误是 ECONNRESET&#xff0c;这通常与网络连接问题相关。设置代理解决问题。 一、查看当前代理设置 npm config get proxy npm config get https-proxy二、设置代理 npm config set proxy http://your-proxy-address:port npm config set h…

单元测试3.0+ @RunWith(JMockit.class)+mock+Expectations

Jmockit使用笔记_基本功能使用Tested_Injectable_Mocked_Expectations_jmockit.class-CSDN博客 测试框架Jmockit集合junit使用 RunWith(JMockit.class) 写在测试案例类上的注解 Tested 在测试案例中,写在我们要测试的类上面, 一般用实现类 Injectable 在测试案例中声明…

网络渗透测试实验二:网络嗅探与身份认证

1.实验目的和要求 1、通过使用Wireshark软件掌握Sniffer&#xff08;嗅探器&#xff09;工具的使用方法&#xff0c;实现捕捉HTTP等协议的数据包&#xff0c;以理解TCP/IP协议中多种协议的数据结构、通过实验了解HTTP等协议明文传输的特性。 2、研究交换环境下的网络嗅探实现…

mqtt连接onenet云平台

密码 version2018-10-31&resproducts%2FlzNd7drwE2%2Fdevices%2Flocation_1&et1756617761&methodmd5&sign52jsIUhK7i2zXjlEtkwDhQ%3D%3D 设备名称&#xff1a;temperatureAndHumidity 设备密钥&#xff1a;bE5OSHBlTHU3TDNSUUVoTmY0WWZqbThDVzNjOUJ3Y1Y 产品i…

Neo4j GDS 2.0 安装与配置

Neo4j GDS 2.0 安装与配置 GDS插件安装&#xff1a;Neo4j官方文档 1. GDS简介 Neo4j Graph Data Science (GDS) 库作为 Neo4j Graph Database 的插件提供。该插件需要安装到数据库中并在 Neo4j 配置中列入白名单。有两种主要方法可以实现这一点&#xff0c;我们将在本章中详…

艾体宝方案丨全面提升API安全:AccuKnox 接口漏洞预防与修复

一、API 安全&#xff1a;现代企业的必修课 在现代技术生态中&#xff0c;应用程序编程接口&#xff08;API&#xff09;扮演着不可或缺的角色。从数据共享到跨平台集成&#xff0c;API 成为连接企业系统与外部服务的桥梁。然而&#xff0c;伴随云计算的普及与微服务架构的流行…

使用JMeter对Linux生产服务器进行压力测试

安装 JMeter wget https://downloads.apache.org/jmeter/binaries/apache-jmeter-5.4.1.tgz tar -xzf apache-jmeter-5.4.1.tgz cd apache-jmeter-5.4.1创建 JMeter 脚本 设置中文 选择Options—>Choose Language—>选择其他语言&#xff08;例如&#xff1a;Chinese&am…

位置编码--RPE

相对位置编码 (Relative Position Encoding, RPE) 1. 相对位置编码 相对位置编码是 Transformer 中的一种改进位置编码方式&#xff0c;它的主要目的是通过直接建模序列中元素之间的相对位置&#xff0c;而不是绝对位置&#xff0c;从而更好地捕捉序列元素之间的依赖关系&#…

《代码随想录》Day21打卡!

写在前面&#xff1a;祝大家新年快乐&#xff01;&#xff01;&#xff01;2025年快乐&#xff0c;2024年拜拜~~~ 《代码随想录》二叉树&#xff1a;修剪二叉搜索树 本题的完整题目如下&#xff1a; 本题的完整思路如下&#xff1a; 1.本题使用递归进行求解&#xff0c;所以分…

【mysql】linux安装mysql客户端

参考文章&#xff1a; MySQL系列之如何在Linux只安装客户端 linux下安装mysql客户端client MySQL Community Downloads 查看linux版本方法&#xff1a; lsb_release -a cat /proc/version下载文件&#xff1a; rpm -ivh mysql-community-*可以删除错误的包&#xff1a; RP…

HTML——26.像素单位

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>像素</title></head><body><!--像素&#xff1a;1.指设备屏幕上的一个点&#xff0c;单位px&#xff0c;如led屏上的小灯朱2.当屏幕分辨率固定时&…

一键闪测仪:MLCC尺寸测量解决方案

MLCC是电子行业中常用的陶瓷电容器&#xff0c;其尺寸影响物理占用空间、电气性能和可靠性等&#xff0c;因此MLCC尺寸管控对产品质量至关重要。 在此&#xff0c;小优博士给各位介绍MLCC的概况以及MLCC尺寸快速测量解决方案。 一、MLCC概述 MLCC&#xff08;Multi-layer Cer…

Spring API 接口加密/解密

API 接口加密/解密 为了安全性需要对接口的数据进行加密处理&#xff0c;不能明文暴露数据。为此应该对接口进行加密/解密处理&#xff0c;对于接口的行为&#xff0c;分别有&#xff1a; 入参&#xff0c;对传过来的加密参数解密。接口处理客户端提交的参数时候&#xff0c;…

学习threejs,导入pdb格式的模型

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️THREE.PDBLoader pdb模型加…

Frontend - 分页(针对 python / Django )

目录 一、同个文件内&#xff08;方式一&#xff09; 1. 前端 html 2. 定义分页界面 3. 获取分页数据 4.后端根据前端分页需求&#xff0c;整理分页数据 5.显示情况 6. JsonResponse 相关知识 二、不同文件内依旧有效&#xff08;方式二&#xff0c;更优化&#xff09;…