SSM-Spring-IOC/DI对应的配置开发
目录
一、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 容器中已经创建了 service
和 dao
对象后,程序仍然无法正常运行,因为 service
对象的正常运行依赖于 dao
对象。但此时,尽管 IOC 容器中已经存在这两个对象,它们之间并没有建立任何联系。
要让 service
对象能够正常运行,就需要将 dao
对象注入到 service
对象中,建立两者之间的依赖关系。这种在容器中为对象之间建立依赖关系的方式,称为 依赖注入(DI,Dependency Injection)。通过 DI,IOC 容器会自动将 dao
对象赋值到 service
的属性中,从而使得 service
可以调用 dao
提供的功能。
5.Spring 容器管理什么内容?
Spring 使用 IOC 容器来管理项目中所使用到的类对象,比如 Service
和 Dao
等。这些对象在项目中被称为 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标签标示配置beanid属性标示给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 容器实例。
常见的实现类有:ClassPathXmlApplicationContext
和 AnnotationConfigApplicationContext
。
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-jdbc
、spring-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标签标示配置beanid属性标示给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的状态特性:
-
有状态对象:如果Bean中包含成员变量用来存储数据,那么在多线程共享同一个Bean实例时,不同线程可能会修改这些成员变量的值,从而导致线程安全问题。
-
无状态对象:如果Bean中没有成员变量,且仅通过方法调用进行操作(方法中使用局部变量),则是线程安全的。因为局部变量是线程私有的,在方法调用完成后会被销毁,因此不存在安全隐患。
在实际开发中,建议对无状态的业务逻辑使用单例模式,而对于有状态的对象,可以考虑通过Spring的其他作用域(如prototype
)来实现每次请求生成一个新对象。
3.哪些Bean对象适合交给Spring容器管理?
适合交给Spring容器管理的Bean对象主要包括以下几类:
-
表现层对象:如控制器类(Controller),用于处理用户的请求并返回相应的结果。
-
业务层对象:如服务类(Service),封装了核心的业务逻辑。
-
数据层对象:如数据访问对象(DAO),负责与数据库进行交互。
-
工具类对象:如日志工具、加密工具等通用工具类,这类对象通常无状态,适合单例管理。
通过交给Spring容器管理,这些对象的生命周期可以被Spring很好地控制,并通过依赖注入(DI)实现对象之间的协作关系。
4.哪些Bean对象不适合交给Spring容器管理?
并不是所有对象都适合交由Spring容器管理,以下几类对象不适合:
-
具有强状态性的对象:例如使用
ThreadLocal
存储线程相关数据的对象,每个线程需要独立的实例,不适合单例管理。 -
短生命周期的临时对象:例如临时使用的工具类对象、结果集对象等,这些对象通常是瞬时的,频繁创建和销毁。如果交给容器管理,反而增加了开销。
-
需要动态创建的对象:例如通过第三方库动态生成的对象,或需要复杂初始化逻辑的对象,这类对象通常需要灵活控制生命周期。
-
底层资源相关的对象:如文件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生命周期中的重要阶段
-
初始化容器:
- 创建对象:在容器中为Bean分配内存。
- 执行构造方法:调用Bean的无参构造方法,完成对象的创建。
- 属性注入:使用
set
方法将依赖注入到Bean中。 - 执行初始化方法:调用Bean的初始化方法,完成对象的初始化操作。
-
使用Bean:
- 调用Bean的业务逻辑方法,完成具体的业务操作。
-
关闭/销毁容器:
- 执行销毁方法:当容器关闭时,调用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/beanshttp://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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://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-依赖注入相关
相关文章:

SSM-Spring-IOC/DI对应的配置开发
目录 一、IOC 控制反转 1.什么是控制反转呢 2. Spring和IOC之间的关系是什么呢? 3.IOC容器的作用以及内部存放的是什么? 4.当IOC容器中创建好service和dao对象后,程序能正确执行么? 5.Spring 容器管理什么内容? 6.如何将需要管理的对象交给 …...

一文大白话讲清楚CSS元素的水平居中和垂直居中
文章目录 一文大白话讲清楚CSS元素的水平居中和垂直居中1.已知元素宽高的居中方案1.1 利用定位margin:auto1.2 利用定位margin负值1.3 table布局 2.未知元素宽高的居中方案2.1利用定位transform2.2 flex弹性布局2.3 grid网格布局 3. 内联元素的居中布局 一文大白话讲清楚CSS元素…...

航顺芯片推出HK32A040方案,赋能汽车矩阵大灯安全与智能化升级
汽车安全行驶对整车照明系统的要求正在向智能化方向发展。车灯位于汽车两侧,前期有各种各样的实现包括氙气灯、LED灯等等光源技术。矩阵大灯对汽车照明系统朝着安全性和智能化兼具的方向发展起到了重要推动作用。矩阵大灯可以精细控制到每一个小灯珠,从而…...

智能工厂的设计软件 应用场景的一个例子:为AI聊天工具添加一个知识系统 之12 方案再探:特定于领域的模板 之2 首次尝试和遗留问题解决
本文提要 现在就剩下“体”本身的 约定了--这必然是 自律自省的,或者称为“戒律” --即“体”的自我训导discipline。完整表述为: 严格双相的庄严“相” (<head>侧),完全双性的本质“性”(<boot>侧&…...

redis zset底层实现
1.Redis zset底层实现 转载自:https://marticles.github.io/2019/03/19/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3Redis-Zset%E5%8E%9F%E7%90%86/ zset底层是压缩列表 跳表实现的。 跳表里面又由字典hash表 跳表实现。 什么时候用压缩列表?什么时候用…...
go.Bar如何让hovertext显示为legend
在 Plotly 的 go.Bar 图中,如果你想让鼠标悬停时 (hover) 显示的文本 (hovertext) 与图例 (legend) 一致,可以通过 hovertemplate 来控制悬停时的显示内容。 实现方法 hovertemplate 是一种自定义工具,允许你完全控制悬停时的文本显示格式。…...

【Vue】分享一个快速入门的前端框架以及如何搭建
先上效果图: 登录 菜单: 下载地址: 链接:https://pan.baidu.com/s/1m-ZlBARWU6_2n8jZil_RAQ 提取码:ui20 … 主要是可以自定义设置token,更改后端请求地址较为方便。 应用设置: 登录与token设置: 在这里设置不用登录,可以请求的接口: request.js i…...

Flink源码解析之:如何根据JobGraph生成ExecutionGraph
Flink源码解析之:如何根据JobGraph生成ExecutionGraph 在上一篇Flink源码解析中,我们介绍了Flink如何根据StreamGraph生成JobGraph的流程,并着重分析了其算子链的合并过程和JobGraph的构造流程。 对于StreamGraph和JobGraph的生成来说&…...
UE(虚幻)学习(三) UnrealSharp插件中调用非托管DLL
上一篇文章中我使用UnrealSharp成功使用了我的一个C#控制台程序中的网络模块,这个程序是基于KCP网络了,其中调用了Cmake 编译的一个C的DLL,在虚幻中DLL需要放在Binaries目录中才可以。Unity中只要放在任意Plugins目录中就可以。 但是Binaries…...
leetcode 3219. 切蛋糕的最小总开销 II
题目:3219. 切蛋糕的最小总开销 II - 力扣(LeetCode) 排序贪心。 开销越大的越早切。 注意m或n为1的情况。 class Solution { public:long long minimumCost(int m, int n, vector<int>& horizontalCut, vector<int>&…...
vant 地址记录
vant ui 的官网地址记录 vant 4 Vant 4 - A lightweight, customizable Vue UI library for mobile web apps. vant2 https://vant-ui.github.io/vant/v2/ vant3 Vant 3 - Lightweight Mobile UI Components built on Vue...

Lua语言入门 - Lua常量
在Lua中,虽然没有直接的常量关键字(如C中的const),但你可以通过一些编程技巧和约定来实现类似常量的行为。以下是几种常见的方法: 1. 使用全局变量并命名规范 你可以定义一个全局变量,并通过命名约定来表示…...
在Microsoft Windows上安装MySQL
MySQL仅适用于Microsoft Windows 64位操作系统,在Microsoft Windows上安装MySQL有不同的方法:MSI、包含您解压缩的所有必要文件的标准二进制版本(打包为压缩文件)以及自己编译MySQL源文件。 注意:MySQL8.4服务器需要在…...

windows下vscode使用msvc编译器出现中文乱码
文章目录 [toc]1、概述2、修改已创建文件编码3、修改vscode默认编码 更多精彩内容👉内容导航 👈👉C 👈👉开发工具 👈 1、概述 在使用MSVC编译器时,出现中文报错的问题可能与编码格式有关。UTF-…...
Git 解决 everything up-to-date
首先使用git log查看历史提交,找到最新一次提交,比如: PS D:\Unity Projects\CoffeeHouse\CoffeeHouse_BurstDebugInformation_DoNotShip> git log commit a1b54c309ade7c07c3981d3ed748b0ffac2759a3 (HEAD -> master, origin/master)…...

Windows配置cuda,并安装配置Pytorch-GPU版本
文章目录 1. CUDA Toolkit安装2. 安装cuDNN3. 添加环境变量配置Pytorch GPU版本 博主的电脑是Windows11,在安装cuda之前,请先查看pytorch支持的版本,cuda可以向下兼容,但是pytorch不行,请先进入:https://py…...
Neo4j 图数据库安装与操作指南(以mac为例)
目录 一、安装前提条件 1.1 Java环境 1.2 Homebrew(可选) 二、下载并安装Neo4j 2.1 从官方网站下载 2.1.1 访问Neo4j的官方网站 2.1.2 使用Homebrew安装 三、配置Neo4j 3.1 设置环境变量(可选) 3.2 打开配置文件(bash_profile) 3.2.1 打开终端…...
2024年12月个人工作生活总结
本文为 2024年12月工作生活总结。 研发编码 Golang语言byte数组赋值 假定有如下变量: var strCode string var bCode [9]byte现需将string类型转换成byte类型,如下: bCode []byte(strCode)无法转换,提示: cannot…...

PHP:IntelliJ IDEA 配置 PHP 开发环境及导入PHP项目
在创建PHP项目之前我们需要安装PHP插件,安装步骤如下:Windows:IntelliJ IDEA Ultimate 安装 PHP 插件-CSDN博客 1、导入已有PHP项目,导入之后选择,File > Setting 选择对应CLL Interpreter,如果没有操作…...

【嵌入式C语言】指针数组结构体
指针与数组 指针与数组指针数组数组指针 多维数组数组名的保存 结构体定义结构体定义结构体变量使用typedef简化结构体声明访问结构体成员结构体内存分配字节对齐位域定义位域位域的限制示例 指针与数组 指针数组和数组指针是两个不同的概念,它们涉及到指针和数组的…...

C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...

Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建
制造业采购供应链管理是企业运营的核心环节,供应链协同管理在供应链上下游企业之间建立紧密的合作关系,通过信息共享、资源整合、业务协同等方式,实现供应链的全面管理和优化,提高供应链的效率和透明度,降低供应链的成…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
【JavaSE】绘图与事件入门学习笔记
-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...

面向无人机海岸带生态系统监测的语义分割基准数据集
描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...

从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践
作者:吴岐诗,杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言:融合数据湖与数仓的创新之路 在数字金融时代,数据已成为金融机构的核心竞争力。杭银消费金…...

Unity UGUI Button事件流程
场景结构 测试代码 public class TestBtn : MonoBehaviour {void Start(){var btn GetComponent<Button>();btn.onClick.AddListener(OnClick);}private void OnClick(){Debug.Log("666");}}当添加事件时 // 实例化一个ButtonClickedEvent的事件 [Formerl…...