什么是IOC
Inversion of Control的缩写,中文译为控制反转,简单来说就是把对象创建和对象之间的调用过程,交给 Spring 进行管理。
创建对象实例的控制权从代码控制剥离到IOC容器控制,实际就是你在xml文件控制,侧重于原理
底层原理
- XML解析
使用dom4j解析 - 工厂模式
- 反射创建类对象
1 | Class clazz=Class.forName(classValue); |
XML注入实现IOC
注入常规类型属性
set方法注入
- 第一步 在类中定义属性和对应的 set 方法
- 第二步 在XML文件中添加property标签
1 | <!--配置User对象--> |
有参构造注入
- 第一步 在类中定义有参构造方法
- 第二步 在XML文件中添加constructor-arg标签
1 | <!--配置User对象--> |
P空间注入(了解)
- 第一步 在类中定义属性和对应的 set 方法
- 第二步 修改XML文件
在beans中添加xmlns:p属性;在bean中添加p:name属性
1 |
|
注入特殊类型属性
空值
1 | <property name="name"> |
特殊符号
-
方法一 把<>进行转义
1
2<property name="name" value="<<王五>>">
</property> -
把带特殊符号内容写到 CDATA
1
2
3<property name="name">
<value><![CDATA[<<王五>>]]></value>
</property>
外部Bean
现有类UserService、接口UserDao、类UserDaoImpl,其中UserDaoImpl实现了接口UserDao。代码结构如下:
1 | src |
如果类UserService要调用类UserDaoImpl的方法,传统做法是创建UserDao对象然后调用其方法,这种做法耦合太高。用spring注入的步骤如下:
- 在UserService中创建属性UserDao,并写好set方法
- 在XML中配置UserService和UserDao对象
- 通过property标签注入UserDao对象
示例代码如下:
接口UserDao:
1 | public interface UserDao { |
类UserDaoImpl:
1 | public class UserDaoImpl implements UserDao { |
类UserService:
1 | public class UserService { |
bean.xml:
1 | <bean id="userDaoImpl" class="com.spring5.dao.UserDaoImpl"></bean> |
内部Bean和级联配置
简单来说就是bean标签里面嵌套bean标签。在员工和部门,一个部门有多个员工,一个员工属于一个部门。示例代码如下:
Dept类:
1 | public class Dept { |
Emp类
1 | public class Emp { |
内部Bean配置
1 | <!--内部 bean--> |
级联配置
Emp类需要生成getDep的方法
1 | public Dept getDept(){ |
XML文件中dept.dname获取属性
1 | <!--级联赋值--> |
注入集合属性
普通注入
新建类User,包含集合属性和相关set方法
1 | public class User { |
XML配置
1 | <bean id= "user" class= "com.spring5.User"> |
注入对象集合
Dept类
1 | public class Dept { |
Emp类
1 | public class Emp { |
XML配置
1 | <bean id= "dept" class= "com.spring5.Dept"> |
自动装配
Spring可以根据属性名称或者类型进行自动装配,使用byType时相同类型的Bean不能配置多个。
1 | <bean id= "emp" class= "com.spring5.autowire.Emp" autowire="byType"> |
外部属性文件
一、创建外部属性文件jdbc.properties,填写数据库信息,key随便写
1 | prop.driverClass=com.mysql.jdbc.Driver |
二、把外部 properties 属性文件引入到 spring 配置文件中
-
引入 context 名称空间
xmlns:context=“http://www.springframework.org/schema/context”
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring- - context.xsd" -
在 spring 配置文件使用标签引入外部属性文件
1 | <beans xmlns="http://www.springframework.org/schema/beans" |
工厂Bean
Spring 有两种类型:普通 bean和工厂bean(FactoryBean)。普通 bean在配置文件中定义的bean类型和返回类型一样,而工厂bean在配置文件定义 bean类型可以和返回类型不一样。实现工厂Bean的步骤如下:
- 第一步 创建类,让这个类作为工厂 bean,实现FactoryBean接口
- 第二步 重写接口里面的方法,在方法中定义返回的bean类型
示例代码如下:
MyBean和User类
1 | public class MyBean implements FactoryBean<User> { |
bean.xml
1 | <bean id="myBean" class="com.spring5.MyBean"></bean> |
Test类
1 | public class Test { |
运行结果:
com.spring5.User@42d8062c
I am test…
Bean的作用域
作用域 | 说明 |
---|---|
单例(singleton) | 默认)每一个Spring IoC容器都拥有唯一的一个实例对象 |
原型(prototype) | 一个Bean定义,任意多个对象 |
请求(request) | 一个HTTP请求会产生一个Bean对象,也就是说,每一个HTTP请求都有自己的Bean实例。只在基于web的Spring ApplicationContext中可用 |
会话(session) | 限定一个Bean的作用域为HTTPsession的生命周期。同样,只有基于web的Spring ApplicationContext才能使用 |
全局会话(global session) | 限定一个Bean的作用域为全局HTTPSession的生命周期。通常用于门户网站场景,同样,只有基于web的Spring ApplicationContext可用 |
Bean的生命周期
-
第一步,执行无参构造创建Bean实例
-
第二步,调用类的set方法设置属性值
-
第三步,调用预初始化方法postProcessBeforeInitialzation()
需要有Bean实现了BeanPostProcessor接口 -
第四步,调用bean的初始化的方法
需要在XML的bean属性中进行配置1
init-method="初始化调用方法名"
-
第五步,调用后初始化方法postProcessAfterInitialization()
需要有Bean实现了BeanPostProcessor接口 -
第六步,对象获取到了,bean可以使用了
-
第七步,当容器关闭时调用bean的销毁的方法
需要在XML的bean属性中进行配置1
destroy-method="销毁调用方法名"
实例代码如下:
User类
1 | public class User { |
MyBeanPost类
1 | public class MyBeanPost implements BeanPostProcessor { |
Test类
1 | public class Test { |
bean.xml
1 | <!--配置User对象--> |
注解方式实现IOC
注解概述
- 注解是代码特殊标记
语法:@注解名称(属性名称=属性值, 属性名称=属性值…) - 怎么用注解
注解可以用在类、方法和属性上面 - 使用注解目的
简化 xml 配置
Spring针对 Bean管理中创建对象提供的注解
- @Component
- @Service
- @Controller
- @Repository
上面四个注解功能是一样的,都可以用来创建 bean 实例,在服务层用@Service、在控制层用@Controller只是方便管理。
实现对象创建
- 第一步 引入依赖
把spring-aop-5.2.6.RELEASE.jar包引入到IDEA中 - 第二步 开启组件扫描
需要引入context名称空间:xmlns:context=“http://www.springframework.org/schema/context”、http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"
1 | <!--开启组件扫描 |
- 第三步 创建类,在类上面添加注解
注解中的value值可以省略,默认值是类名首字母小写
1 |
|
扫描细节配置
- 不加use-default-filters="false"表示会扫描包下面的所有注解
- context:include-filter 配置扫描哪些内容
- context:exclude-filter配置不扫描哪些内容
示例一
1 | <!--扫描包com.spring5下面@Controller注解--> |
示例二
1 | <!--扫描包com.spring5下面除了@Controller以外的所有注解--> |