我们该用BeanFactory还是ApplicationContent???
FileSystemXmlApplicationContext
序言
Spring学习笔记-IOC(一)_Tensorflow-CSDN博客https://blog.csdn.net/weixin_43715214/article/details/123244453上述文章讲述了Spring-IOC中的XML配置的bean的部分,后序内容请见下文
- bean(以讲)
- DI
- set注入
- 构造方法注入
- 集合类型数据注入
- 使用p命名空间简化配置
properties文件
- ApplicationContext
IOC配置(XML)
DI(依赖注入)
概念
IoC(Inversion Of Control)控制翻转,Spring反向控制应用程序所需要使用的外部资源
DI(Dependency Injection)依赖注入,应用程序运行依赖的资源由Spring为其提供,资源进入应用程序的方式称为注入
DI与IOC之间的关联
应用程序依赖资源,Spring为其注入资源,应用程序不是依赖Spring,而是依赖Spring提供的资源
其实这两件事时在同一时间发生的,只是主、被动关系不同。
站在Spring容器的角度上来看,叫IOC;站在应用程序的角度上来看叫做DI。
DI依赖注入由两种方式——set注入、构造器注入
set注入(主流方式)
set注入后面案例的源码
是Spring_demo02.zip的!
Spring示例代码: 根据黑马程序员的视频课,自己课后练习代码汇总,与本人CSDN文章相对应。https://gitee.com/li_chen_xin_TL/spring-sample-code.git名称是<property>,是<bean>标签下的子标签,使用set方法的形式为bean提供资源
格式
<bean>
<property />
</bean>
案例代码-set注入示例
Dao层的实现类-UserDaoImpl
public class UserDaoImpl implements UserDao {
public void save() {
System.out.println("user dao running...");
}
}
service层的实现类-UserServiceImpl
public class UserServiceImpl implements UserService {
// 注入number (非引用类型)
private int number;
public void setNumber(int number) {
this.number = number;
}
// 1.对需要注入的变量添加set注入
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void save() {
System.out.println("user service running" + number);
userDao.save();
}
}
配置文件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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userService" class="com.itheima.service.impl.UserServiceImpl">
<!-- 3.将要注入的引用类型变量,通过property属性注入,对应name是要注入的变量名,使用ref属性声明要注入的bean的id -->
<property name="userDao" ref="userDao"></property>
<property name="number" value="666"></property>
</bean>
<!--2.将要注入的资源声明为bean-->
<bean id="userDao" class="com.itheima.Dao.impl.UserDaoImpl"/>
</beans>
程序执行入口
public class UserApp {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) ctx.getBean("userService");
userService.save();
}
}
问题:spring 到底注入接口还是实现类?
构造器注入(了解)
构造器注入后面案例的源码
是Spring_demo03.zip中的!
Spring示例代码: 根据黑马程序员的视频课,自己课后练习代码汇总,与本人CSDN文章相对应。https://gitee.com/li_chen_xin_TL/spring-sample-code.git在set注入中,是通过属性值注入的,而在构造器注入中,是通过构造方法。
-
名称:constructor-arg
-
类型:标签
-
归属:bean标签
-
作用:使用构造方法的形式为bean提供资源,兼容早期遗留系统的升级工作
-
格式:
<bean>
<constructor-arg />
</bean>
- 基本属性:
<constructor-arg name="argsName" value="argsValue />
name:对应bean中的构造方法所携带的参数名
value:设定非引用类型构造方法参数对应的值,不能与ref同时使用
- 其他属性:
<constructor-arg index="arg-index" type="arg-type" ref="beanId"/>
ref:设定引用类型构造方法参数对应bean的id ,不能与value同时使用
type :设定构造方法参数的类型,用于按类型匹配参数或进行类型校验
index :设定构造方法参数的位置,用于按位置匹配参数,参数index值从0开始计数
注意:一个bean可以有多个constructor-arg标签
案例代码-构造器注入示例
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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userDao" class="com.itheima.Dao.impl.UserDaoImpl"/>
<bean id="userService" class="com.itheima.service.impl.UserServiceImpl">
<constructor-arg ref="userDao"/>
<constructor-arg name="number" value="100"/>
<constructor-arg name="age" value="18"/>
</bean>
</beans>
UserServiceImpl实现类
public class UserServiceImpl implements UserService {
private UserDao userDao;
private int number;
private int age;
public UserServiceImpl(UserDao userDao,int number,int age ) {
this.userDao = userDao;
this.number = number;
this.age = age;
}
public void save() {
System.out.println("user service running" + " " + number + " " + age);
userDao.save();
}
}
UserApp
public class UserApp {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) ctx.getBean("userService");
userService.save();
}
}
集合注入(5种)
源码如下:
Spring_demo04.zip
- 名称:array,list,set,map,props
- 类型:标签
- 归属:property标签 或 constructor-arg标签
- 作用:注入集合数据类型属性
- 格式:
<property>
<list></list>
</property>
array
list
set
map
props
代码演示
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
<property name="al">
<list>
<value>itheima</value>
<value>66666</value>
</list>
</property>
<property name="properties">
<props>
<prop key="name">itheima666</prop>
<prop key="value">666666</prop>
</props>
</property>
<property name="arr">
<array>
<value>123456</value>
<value>66666</value>
</array>
</property>
<property name="hs">
<set>
<value>itheima</value>
<value>66666</value>
</set>
</property>
<property name="hm">
<map>
<entry key="name" value="itheima66666"/>
<entry key="value" value="6666666666"/>
</map>
</property>
</bean>
注意:上述代码中会有一点小问题,虽然不会影响运行
就是在声明List的时候,如果是用private ArrayList<String> al;
在xml文件的<List>标签下面会有一个红色的小横线!
有两种处理办法:
(1)将之前的声明改为private List<String> al; 后面的HashMap和HashSet也会出现类似问题,处理方法也是改为Map 和 Set就行了
(2)看这里
使用p命名空间简化配置
源码如下
Spring_demo05.zip
Spring示例代码: 根据黑马程序员的视频课,自己课后练习代码汇总,与本人CSDN文章相对应。https://gitee.com/li_chen_xin_TL/spring-sample-code.git简单的来说就是为了简化写法,之前的一个bean标签,要注入的的话,里面会有多个<property>标签,但是我们可以使用p命名空间来简化写法(效果和作用是一样的!)
首先使用p命令空间需要先开启spring对p命令空间的的支持,在beans标签中添加对应空间支持
xmlns:p="http://www.springframework.org/schema/p"
然后,我们原先的写法是:
<bean id="userService" class="com.Harmony.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"/>
<property name="bookDao" ref="bookDao"/>
</bean>
向UserServiceImpl实现类注入userDao和bookDao对象
使用命名空间p,我们可以这样写:
<bean id="userService"
class="com.Harmony.service.impl.UserServiceImpl"
p:bookDao-ref="bookDao"
p:userDao-ref="userDao"
/>
作用效果是一样的!
注:后面的 “-ref” ,是因为其为引用数据类型,如果为数值类型就不用加!
properties文件
Spring提供了读取外部properties文件的机制,使用读取到的数据为bean的属性赋值
操作步骤
1.准备外部properties文件
2.开启context命名空间支持 和 schema
空间声明
xmlns:context="http://www.springframework.org/schema/context"
schma
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
完整的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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
</beans>
3.加载指定的properties文件
<context:property-placeholder location="classpath:filename.properties">
filename.properties:
可以使用“*”全部加载
<context:property-placeholder location="classpath:*.properties">
4.使用加载的数据
<property name="propertyName" value="${propertiesName}"/>
-
注意:读取数据使用${propertiesName}格式进行,其中propertiesName指properties文件中的属性名
ApplicationContext
概述
1.ApplicationContext是一个接口,提供了访问spring容器的API
2.ClassPathXmlApplicationContext是一个类,实现了上述功能
3.ApplicationContext的顶层接口是BeanFactory
4.BeanFactory定义了bean相关的最基本操作
5.ApplicationContext在BeanFactory基础上追加了若干新功能
两者区别
1.BeanFactory创建的bean采用延迟加载形式,使用才创建
2.ApplicationContext创建的bean默认采用立即加载形式
我们该用BeanFactory还是ApplicationContent???
延迟实例化的优点:(BeanFactory)
应用启动的时候占用资源很少;对资源要求较高的应用,比较有优势;
不延迟实例化的优点: (ApplicationContext)
1. 所有的Bean在启动的时候都加载,系统运行的速度快;
2. 在启动的时候所有的Bean都加载了,我们就能在系统启动的时候,尽早的发现系统中的配置问题
3. 建议web应用,在启动的时候就把所有的Bean都加载了。(把费时的操作放到系统启动中完成)
FileSystemXmlApplicationContext
可以加载文件系统中任意位置的配置文件,而ClassPathXmlApplicationContext只能加载类路径下的配置文件