IOC介绍
- IOC容器
- 底层原理
- IOC接口
- IOC操作Bean管理
- IOC 操作 Bean 管理(基于 xml 方式)
- 第一种注入方式:使用 set 方法进行注入
- 第二种注入方式:使用 有参构造 进行注入
- 第三种注入方式:使用 p名称空间 进行注入
- 注入空值和特殊字符
- 注入属性:外部bean
- 注入属性:内部bean
- 注入属性:级联赋值
- 注入集合属性
- 集合里面设置对象值
- 将集合提取出去,使之成为公共部分
- Bean管理(工厂bean)
- Bean的作用域
- Bean生命周期
- 自动装配
- 引入外部属性文件
- IOC操作 Bean管理(基于注解方式)
- 创建对象
- 组件扫描细节配置
- 基于注解方式实现属性注入
- 完全注解开发
IOC容器
- 控制反转,把对象创建和对象之间的调用过程,交给 Spring 进行管理
- 使用目的:降低耦合度
IOC底层原理
1、在 Spring的配置文件中,配置创建的对象
2、设计一个工厂模式的类,类中利用 xml解析技术(dom4j) 取出类的全路径,并通过反射技术,返回一个该类的对象
3、其他类可以通过工厂类,来获得其他对象,从而实现对象与对象之间的调用
IOC接口
- IOC 思想基于 IOC 容器完成,IOC 容器底层就是对象工厂
- Spring 提供 IOC 容器实现两种方式:(两个接口)
(1)、BeanFactory:IOC 容器基本实现,是 Spring 内部的使用接口,不提供开发人员进行使用
- 加载配置文件时候不会创建对象,在获取对象(使用)才去创建对象
(2)、ApplicationContext:BeanFactory 接口的子接口,提供更多更强大的功能,一般由开发人
员进行使用
- 加载配置文件时候就会把在配置文件对象进行创建
IOC操作Bean管理
- 什么是 Bean 管理
- Spring 创建对象
- Spirng 注入属性
- Bean 管理操作有两种方式
- 基于 xml 配置文件方式实现
- 基于注解方式实现
IOC 操作 Bean 管理(基于 xml 方式)
创建对象
- 在 Spring 配置文件中,使用 bean 标签,标签里面添加对应属性,就可以实现对象创建
- 在 bean 标签有很多属性,介绍常用的属性
- id 属性:唯一标识
- class 属性:类全路径(包类路径)
- 创建对象时候,默认执行无参数构造方法完成对象创建
注入方式
1、set 方法
类中需提供属性的set方法
<bean id="book" class="com.study.spring5.Book"><property name="bname" value="西游记"></property></bean>
2、使用 有参构造 进行注入
类中需提供 有参 构造
<bean id="orders" class="com.study.spring5.Orders"><constructor-arg name="oname" value="上海"></constructor-arg></bean>
3、使用p名称空间 进行注入
在Spring的配置文件中,添加 p 名称空间
<bean id="book" class="com.study.spring5.Book" p:bname="三国演义" p:bauthor="罗贯中"></bean>
注入空值和特殊字符
注入空值
<bean id="userDao" class="com.study.spring5.dao.UserDaoImpl"><property name="bname"><null/></property></bean>
注入特殊字符
<bean id="book" class="com.study.spring5.Book"><property name="bname" value="西游记"></property><property name="address"><value><![CDATA[<>]]></value></property></bean>
注入属性:外部bean
一个类中 定义了 另一个 类 的属性
<bean id="userService" class="com.study.spring5.service.UserService"></bean><property name="userDao" ref="userDaoImpl"></property><bean id="userDaoImpl" class="com.study.spring5.dao.UserDaoImpl"></bean>
注入属性:内部bean
效果与 外部bean 相同(一个类包含另一个类的对象),只是 配置bean在Spring配置文件中的位置不同
<bean id="emp" class="com.study.spring5.bean.Emp"><property name="dept"><bean id="dept" class="com.study.spring5.bean.Dept"><property name="dname" value="职工"></property></bean></property></bean>
注入属性:级联赋值
级联赋值:是在一个bean对象中注入另一个bean对象(外部bean)的属性并对该属性进行赋值。
第一种写法
<bean id="emp" class="com.study.spring5.bean.Emp"><property name="dept" ref="dept"></property></bean><bean id="dept" class="com.study.spring5.bean.Dept"><property name="dname" value="财务部"></property></bean>
第二种写法
<bean id="emp" class="com.study.spring5.bean.Emp"><property name="dept" ref="dept"></property><property name="dept.dname" value="技术部"></property></bean><bean id="dept" class="com.study.spring5.bean.Dept"></bean>
注入集合属性
注入数组
<bean id="stu" class="com.study.spring5.collectiontype.Stu"><property name="courses"><array><value>Java课程</value><value>数据库课程</value></array></property></bean>
注入list
<bean id="stu" class="com.study.spring5.collectiontype.Stu"><property name="list"><list><value>张三</value><value>李四</value></list></property></bean>
注入set
<bean id="stu" class="com.study.spring5.collectiontype.Stu"><property name="set"><set><value>MySQL</value><value>Redis</value></set></property></bean>
注入map
<bean id="stu" class="com.study.spring5.collectiontype.Stu"><property name="maps"><map><entry key="JAVA" value="java"></entry><entry key="PHP" value="php"></entry></map></property></bean>
集合里面设置对象值
<bean id="stu" class="com.study.spring5.collectiontype.Stu"><property name="courseList"><list><ref bean="course1"></ref><ref bean="course2"></ref></list></property></bean><bean id="course1" class="com.study.spring5.collectiontype.Course"><property name="cname" value="Spring5框架"></property></bean><bean id="course2" class="com.study.spring5.collectiontype.Course"><property name="cname" value="MyBatis框架"></property></bean>
将集合提取出去,使之成为公共部分
添加util名称空间
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
提取集合,并注入
<util:list id="bookList"><!--如果集合里面是对象值,用--><!----><value>西游记</value><value>三国演义</value><value>红楼梦</value></util:list><bean id="book" class="com.study.spring5.collectiontype.Book"><property name="list" ref="bookList"></property></bean>
Bean管理(工厂bean)
1、Spring 有两种类型 bean,一种普通 bean,另外一种工厂 bean(FactoryBean)
2、普通 bean:在配置文件中定义 bean 类型就是返回类型
3、工厂 bean:在配置文件定义 bean 类型可以和返回类型不一样
Bean的作用域
1、在 Spring 里面,设置创建 bean 实例是单实例还是多实例
2、在 Spring 里面,默认情况下,bean 是单实例对象
设置对象为多实例
- 在 spring 配置文件 bean 标签里面有属性(scope)用于设置单实例还是多实例
- scope 属性值
● singleton:默认值,表示是单实例对象
● prototype:表示是多实例对象
singleton 和 prototype 区别
- singleton 单实例,prototype 多实例
- 设置 scope 值是 singleton 时候,加载 spring 配置文件时候就会创建单实例对象
设置 scope 值是 prototype 时候,调用 getBean 方法时候创建多实例对象
<bean id="book" class="com.study.spring5.collectiontype.Book" scope="prototype"><property name="list" ref="bookList"></property></bean>
Bean生命周期
- 生命周期:从对象创建到对象销毁的过程
Bean 生命周期
1、通过构造器创建 bean 实例(无参数构造)
2、为 bean 的属性设置值和对其他 bean 引用(调用 set 方法)
3、调用 bean 的初始化的方法(需要进行配置初始化的方法)
4、bean 可以使用了(对象获取到了)
5、当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法)
在类中创建执行初始化和执行销毁的方法
//创建执行的初始化的方法public void initMethod() {System.out.println("第三步 执行初始化方法");}public void destroyMethod(){System.out.println("第五步 执行销毁方法");}
<bean id="orders" class="com.study.spring5.bean.Orders" init-method="initMethod" destroy-method="destroyMethod"><property name="oname" value="手机"></property></bean>
测试时,需手动销毁
//手动让bean实例销毁((ClassPathXmlApplicationContext) context).close();
后置处理器
- 如果添加了后置处理器,那么Bean的生命周期有七步
1、通过构造器创建 bean 实例(无参数构造)
2、为 bean 的属性设置值和对其他 bean 引用(调用 set 方法)
3、把 bean 实例传递 bean 后置处理器的方法 postProcessBeforeInitialization
4、调用 bean 的初始化的方法(需要进行配置初始化的方法)
5、把 bean 实例传递 bean 后置处理器的方法 postProcessAfterInitialization
6、bean 可以使用了(对象获取到了)
7、当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法)
创建类,实现接口 BeanPostProcessor,创建后置处理器
public class MyBeanPost implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("在初始化之前执行的方法");return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("在初始化之后执行的方法");return bean;}}
在配置文件中配置了后置处理器,那么会为在配置文件中所有bean都添加后置处理器
<bean id="orders" class="com.study.spring5.bean.Orders" init-method="initMethod" destroy-method="destroyMethod"><property name="oname" value="手机"></property></bean><bean id="myBeanPost" class="com.study.spring5.bean.MyBeanPost"></bean>
自动装配
根据指定装配规则(属性名称或者属性类型),Spring 自动将匹配的属性值进行注入
<bean id="emp" class="com.study.spring5.autowire.Emp" autowire="byName"></bean><bean id="dept" class="com.study.spring5.autowire.Dept"></bean>
引入外部属性文件
加入 context
名称空间
<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/spring-context.xsd">
<context:property-placeholder location="classpath:jdbc.properties"/><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="${prop.driverClass}" /><property name="url" value="${prop.url}" /><property name="username" value="${prop.username}" /><property name="password" value="${prop.password}" /></bean>
IOC操作 Bean管理(基于注解方式)
创建对象
- @Component:普通组件
- @Service:一般用于业务逻辑层或service层上
- @Controller:一般用于web层
- @Repository:一般用于dao层
上面四个注解功能是一样的,都可以用来创建 bean 实例
1、引入aop依赖
2、添加名称空间 context
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" 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/spring-context.xsd">
3、开启组件扫描
<context:component-scan base-package="com.study.spring5"></context:component-scan>
4、创建类,在类上面添加创建对象注解
//@Component(value = "userService") 等同于 //注解后面的 values 是设置 id//class 不需要指定,因为开启组件扫描,Spring扫描到这,发现是bean,自然会得到这个类的全路径//在注解里面value属性值可以省略不写,//默认值是类名称,首字母小写//UserService -- userService@Component(value = "userService")public class UserService {public void add() {System.out.println("UserService调用了add.......");}}
组件扫描细节配置
<context:component-scan base-package="com.study" use-default-filters="false"><context:include-filter type="annotation"expression="org.springframework.stereotype.Controller"/></context:component-scan>
<context:component-scan base-package="com.study"><context:exclude-filter type="annotation"expression="org.springframework.stereotype.Controller"/></context:component-scan>
基于注解方式实现属性注入
@Autowired
:根据属性类型进行自动装配@Qualifier
:根据名称进行注入@Resource
:可以根据类型注入,可以根据名称注入@Value
:注入普通类型属性
@Autowired
:根据属性类型进行自动装配
@Servicepublic class UserService {//定义dao类型属性//不需要添加set方法//添加注入属性注解@Autowired //根据类型注入private UserDao userDao;public void add() {System.out.println("UserService调用了add.......");userDao.add();}}
@Qualifier
:根据名称进行注入
这个@Qualifier
注解的使用,和上面@Autowired
一起使用
@Autowired
是根据 属性类型来注入,但如果有多个相同类型的bean,使用这个注解就麻烦了,比如接口的实现类
因此,使用 @Qualifier
通过名称(注解设置的 value) 就可以很好的解决这个问题
//默认的value是 类的名称(第一个字母小写)@Repository(value = "userDaoImpl1")public class UserDaoImpl implements UserDao {}
public class UserService {@Autowired //根据类型注入@Qualifier(value = "userDaoImpl1") //指定valueprivate UserDao userDao;
@Resource
:可以根据类型注入,可以根据名称注入
//类型注入@Resourceprivate UserDao userDao;//名称注入@Resource(name = "userDaoImpl1")private UserDao userDao;
@Value
:注入普通类型属性
@Value("张三")private String name;
完全注解开发
创建配置类,替代 xml 配置文件
@Configuration //作为配置类,替代xml配置文件@ComponentScan(basePackages = "com.study.spring5")public class SpringConfig {}
测试时,这样获取
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
IOC容器
1、什么是 IOC
(1)控制反转,把对象创建和对象之间的调用过程,交给 Spring 进行管理
(2)使用 IOC 目的:为了耦合度降低
底层原理
2、IOC 底层原理
(1)xml 解析、工厂模式、反射
1、在 Spring.xml文件中,配置创建的对象
2、设计一个工厂模式
的类,类中利用 xml解析
技术(dom4j) 取出类的全路径,并通过反射
技术,返回一个该类的对象
3、其他类可以通过工厂类,来获得其他对象,从而实现对象与对象之间的调用
IOC接口
1、IOC 思想基于 IOC 容器完成,IOC 容器底层就是对象工厂
2、Spring 提供 IOC 容器实现两种方式:(两个接口)
(1)BeanFactory:IOC 容器基本实现,是 Spring 内部的使用接口,不提供开发人员进行使用
- 加载配置文件时候不会创建对象,在获取对象(使用)才去创建对象
(2)ApplicationContext:BeanFactory 接口的子接口,提供更多更强大的功能,一般由开发人
员进行使用
- 加载配置文件时候就会把在配置文件对象进行创建
3、ApplicationContext 接口有实现类
FileSystemXmlApplicationContext:系统盘下的Spring 配置的 xml文件
ClassPathXmlApplicationContext:src目录下的Spring 配置的 xml文件
IOC操作Bean管理
1、什么是 Bean 管理
(0)Bean 管理指的是两个操作
(1)Spring 创建对象
(2)Spirng 注入属性
2、Bean 管理操作有两种方式
(1)基于 xml 配置文件方式实现
(2)基于注解方式实现
IOC 操作 Bean 管理(基于 xml 方式)
1、基于 xml 方式创建对象
(1)在 spring 配置文件中,使用 bean 标签,标签里面添加对应属性,就可以实现对象创建
(2)在 bean 标签有很多属性,介绍常用的属性
- id 属性:唯一标识
- class 属性:类全路径(包类路径)
(3)创建对象时候,默认也是执行无参数构造方法完成对象创建
第一种注入方式:使用 set 方法进行注入
Book属性
public class Book {//创建对象private String bname;private String bauthor;//创建对应的set方法public void setBname(String bname) {this.bname = bname;}public void setBauthor(String bauthor) {this.bauthor = bauthor;}public void testDemo() {System.out.println(bname + "::" + bauthor);}}
spring对应的xml文件
<bean id="book" class="com.study.spring5.Book"><property name="bname" value="西游记"></property><property name="bauthor" value="吴承恩"></property></bean>
测试
@Testpublic void bookTest(){//1.加载spring配置文件ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");//2.获取配置创建的对象Book book = context.getBean("book", Book.class);//3.输出book.testDemo();}
第二种注入方式:使用 有参构造 进行注入
Orders
public class Orders {private String oname;private String address;//有参构造public Orders(String oname, String address) {this.oname = oname;this.address = address;}public void ordersTest() {System.out.println(oname + "::" + address);}}
spring对应的xml文件
<bean id="orders" class="com.study.spring5.Orders"><constructor-arg name="oname" value="上海"></constructor-arg><constructor-arg name="address" value="浦东"></constructor-arg></bean>
ordersTest
@Testpublic void ordersTest(){//1.加载spring配置文件ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");//2.获取配置创建的对象Orders orders = context.getBean("orders", Orders.class);//3.输出orders.ordersTest();}
第三种注入方式:使用 p名称空间 进行注入
(1)使用 p 名称空间注入,可以简化基于 xml 配置方式
1、在配置文件中添加 p 名称空间
2、spring对应的xml文件添加标签
在 bean 标签中进行属性注入
<bean id="book" class="com.study.spring5.Book" p:bname="三国演义" p:bauthor="罗贯中"></bean>
3、测试
注入空值和特殊字符
注入空值
<bean id="book" class="com.study.spring5.Book"><property name="bname" value="西游记"></property><property name="bauthor" value="吴承恩"></property><property name="address"><null></null></property></bean>
注入特殊字符
<bean id="book" class="com.study.spring5.Book"><property name="bname" value="西游记"></property><property name="bauthor" value="吴承恩"></property><property name="address"><value><![CDATA[<>]]></value></property></bean>
注入属性:外部bean
(1)创建两个类 service 类和 dao 类
(2)在 service 调用 dao 里面的方法
(3)在 spring 配置文件中进行配置
1、先UserService中,定义dao属性
public class UserService {//创建 UserDao 类型属性,生成 set 方法//UserDao 是一个接口,接口多态private UserDao userDao;public void setUserDao(UserDao userDao) {this.userDao = userDao;}public void add() {System.out.println("service add.....");userDao.update();}}
2、在spring的配置文件中,配置使用的 service 和 dao
<bean id="userService" class="com.study.spring5.service.UserService"></bean><bean id="userDaoImpl" class="com.study.spring5.dao.UserDaoImpl"></bean>
3、在service的标签中,注入 dao 属性
<bean id="userService" class="com.study.spring5.service.UserService"><property name="userDao" ref="userDaoImpl"></property></bean>
4、测试
注入属性:内部bean
(1)一对多关系:部门和员工 (多个对象 包含 一个 相同对象)
(2)在实体类之间表示一对多关系,员工表示所属部门,使用对象类型属性进行表示(员工类中创建一个部门对象)
Emp
public class Emp {private String ename;private String gender;//员工属于某一个部门,使用对象形式表示private Dept dept;public void setDept(Dept dept) {this.dept = dept;}public void setEname(String ename) {this.ename = ename;}public void setGender(String gender) {this.gender = gender;}public void add() {System.out.println(ename + "::" + gender + "::" + dept);}}
2、配置spring的配置文件
<bean id="emp" class="com.study.spring5.bean.Emp"><property name="ename" value="tom"></property><property name="gender" value="男"></property><property name="dept"><bean id="dept" class="com.study.spring5.bean.Dept"><property name="dname" value="职工"></property></bean></property></bean>
3、测试
注入属性:级联赋值
级联赋值:是在一个bean对象中注入另一个bean对象(外部bean)的属性并对该属性进行赋值。
第一种写法
<bean id="emp" class="com.study.spring5.bean.Emp"><property name="ename" value="jack"></property><property name="gender" value="男"></property><property name="dept" ref="dept"></property></bean><bean id="dept" class="com.study.spring5.bean.Dept"><property name="dname" value="财务部"></property></bean>
第二种写法
<bean id="emp" class="com.study.spring5.bean.Emp"><property name="ename" value="jack"></property><property name="gender" value="男"></property><property name="dept" ref="dept"></property><property name="dept.dname" value="技术部"></property></bean><bean id="dept" class="com.study.spring5.bean.Dept"><property name="dname" value="财务部"></property></bean>
要提供被注入对象的get()
方法
注入集合属性
在 Stu类中定义数组、list、set、map属性,并提供set()
方法
spring对应的xml文件
<bean id="stu" class="com.study.spring5.collectiontype.Stu"><property name="courses"><array><value>Java课程</value><value>数据库课程</value></array></property><property name="list"><list><value>张三</value><value>李四</value></list></property><property name="set"><set><value>MySQL</value><value>Redis</value></set></property><property name="maps"><map><entry key="JAVA" value="java"></entry><entry key="PHP" value="php"></entry></map></property></bean>
测试
集合里面设置对象值
定义一个 类型为 Course 的 List 集合
spring对应的xml文件
<bean id="stu" class="com.study.spring5.collectiontype.Stu"><property name="courseList"><list><ref bean="course1"></ref><ref bean="course2"></ref></list></property></bean><bean id="course1" class="com.study.spring5.collectiontype.Course"><property name="cname" value="Spring5框架"></property></bean><bean id="course2" class="com.study.spring5.collectiontype.Course"><property name="cname" value="MyBatis框架"></property></bean>
将集合提取出去,使之成为公共部分
设置:xmlns:util="http://www.springframework.org/schema/util"设置:http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<util:list id="bookList"><!--如果集合里面是对象值,用--><!----><value>西游记</value><value>三国演义</value><value>红楼梦</value></util:list><bean id="book" class="com.study.spring5.collectiontype.Book"><property name="list" ref="bookList"></property></bean><bean id="course1" class="com.study.spring5.collectiontype.Course"></bean>
Bean管理(工厂bean)
1、Spring 有两种类型 bean,一种普通 bean,另外一种工厂 bean(FactoryBean)
2、普通 bean:在配置文件中定义 bean 类型就是返回类型
3、工厂 bean:在配置文件定义 bean 类型可以和返回类型不一样
第一步 创建类,让这个类作为工厂 bean,实现接口 FactoryBean
第二步 实现接口里面的方法,在实现的方法中定义返回的 bean 类型
public class MyBean implements FactoryBean<Course> {//定义返回Bean@Overridepublic Course getObject() throws Exception {Course course = new Course();course.setCname("abc");//返回一个实例return course;}@Overridepublic Class<" />> getObjectType() {//返回实例类型return null;}@Overridepublic boolean isSingleton() {//是否是单例return false;}}
spring对应的xml文件
<bean id="myBean" class="com.study.spring5.factoybean.MyBean"></bean>
测试
@Testpublic void test3() {ApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml");//后面的 xx.class 要是 返回类型的classCourse myBean = context.getBean("myBean", Course.class);System.out.println(myBean.getClass());}
Bean的作用域
1、在 Spring 里面,设置创建 bean 实例是单实例还是多实例
2、在 Spring 里面,默认情况下,bean 是单实例对象
默认单例对象
@Testpublic void test4() {ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");Book book1 = context.getBean("book", Book.class);Book book2 = context.getBean("book", Book.class);System.out.println(book1);System.out.println(book2);}
设置对象为多实例
在 spring 配置文件 bean 标签里面有属性(scope)用于设置单实例还是多实例
scope 属性值
● singleton:默认值,表示是单实例对象
● prototype:表示是多实例对象
singleton 和 prototype 区别
- singleton 单实例,prototype 多实例
- 设置 scope 值是 singleton 时候,加载 spring 配置文件时候就会创建单实例对象
设置 scope 值是 prototype 时候,调用 getBean 方法时候创建多实例对象
<bean id="book" class="com.study.spring5.collectiontype.Book" scope="prototype"><property name="list" ref="bookList"></property></bean>
Bean生命周期
1、生命周期
(1)从对象创建到对象销毁的过程
2、bean 生命周期
- 通过构造器创建 bean 实例(无参数构造)
- 为 bean 的属性设置值和对其他 bean 引用(调用 set 方法)
- 调用 bean 的初始化的方法(需要进行配置初始化的方法)
- bean 可以使用了(对象获取到了)
- 当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法)
Orders类
public class Orders {private String oname;public Orders() {System.out.println("第一步 执行无参构造创建bean对象");}public void setOname(String oname) {this.oname = oname;System.out.println("第二步 调用set方法设置属性值");}//创建执行的初始化的方法public void initMethod() {System.out.println("第三步 执行初始化方法");}public void destroyMethod(){System.out.println("第五步 执行销毁方法");}}
Spring配置文件
<bean id="orders" class="com.study.spring5.bean.Orders" init-method="initMethod" destroy-method="destroyMethod"><property name="oname" value="手机"></property></bean>
获取Bean对象
@Testpublic void testBean3() {ApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");Orders orders = context.getBean("orders", Orders.class);System.out.println("第四步 获取创建bean实例对象");System.out.println(orders);//手动让bean实例销毁((ClassPathXmlApplicationContext) context).close();}
如果添加了后置处理器,那么Bean的生命周期有七步
- 通过构造器创建 bean 实例(无参数构造)
- 为 bean 的属性设置值和对其他 bean 引用(调用 set 方法)
- 把 bean 实例传递 bean 后置处理器的方法 postProcessBeforeInitialization
- 调用 bean 的初始化的方法(需要进行配置初始化的方法)
- 把 bean 实例传递 bean 后置处理器的方法 postProcessAfterInitialization
- bean 可以使用了(对象获取到了)
- 当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法)
1、创建类,实现接口 BeanPostProcessor,创建后置处理器
public class MyBeanPost implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("在初始化之前执行的方法");return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("在初始化之后执行的方法");return bean;}}
2、在配置文件中配置了后置处理器,那么会为在配置文件中所有bean都添加后置处理器
<bean id="orders" class="com.study.spring5.bean.Orders" init-method="initMethod" destroy-method="destroyMethod"><property name="oname" value="手机"></property></bean><bean id="myBeanPost" class="com.study.spring5.bean.MyBeanPost"></bean>
自动装配
1、什么是自动装配
(1)根据指定装配规则(属性名称或者属性类型),Spring 自动将匹配的属性值进行注入
emp
public class Emp {private Dept dept;public void setDept(Dept dept) {this.dept = dept;}@Overridepublic String toString() {return "Emp{" +"dept=" + dept +'}';}
<bean id="emp" class="com.study.spring5.autowire.Emp" autowire="byName"></bean><bean id="dept" class="com.study.spring5.autowire.Dept"></bean>
使用byType,相同类型不能定义多个,否则 报错(根据类型找配置文件中的对象,配置文件配置多个对象,就会造成无法确定是那个对象)
引入外部属性文件
当一个对象要配置的属性很多时,就可以通过引入外部属性来进来配置
以数据库连接池为例
先引入jar包
1、引入外部属性文件配置数据库连接池
(1)创建外部属性文件,properties 格式文件,写数据库信息
jdbc.properties
2、Spring配置文件加入 context
名称空间
<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/spring-context.xsd">xmlns:context="http://www.springframework.org/schema/context"http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
3、在Spring配置文件中 配置连接池
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="${prop.driverClass}" /><property name="url" value="${prop.url}" /><property name="username" value="${prop.username}" /><property name="password" value="${prop.password}" /></bean>
IOC操作 Bean管理(基于注解方式)
创建对象
(1)@Component:普通组件
(2)@Service:一般用于业务逻辑层或service层上
(3)@Controller:一般用于web层
(4)@Repository:一般用于dao层
上面四个注解功能是一样的,都可以用来创建 bean 实例
1、引入aop依赖
2、开启组件扫描
添加名称空间 context
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" 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/spring-context.xsd">
开启组件扫描
<context:component-scan base-package="com.study.spring5"></context:component-scan>
3、创建类,在类上面添加创建对象注解
//@Component(value = "userService") 等同于 //注解后面的 values 是设置 id//class 不需要指定,因为开启组件扫描,Spring扫描到这,发现是bean,自然会得到这个类的全路径//在注解里面value属性值可以省略不写,//默认值是类名称,首字母小写//UserService -- userService@Component(value = "userService")public class UserService {public void add() {System.out.println("UserService调用了add.......");}}
测试
@Testpublic void addTest() {ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");UserService userService = context.getBean("userService", UserService.class);userService.add();}
组件扫描细节配置
<context:component-scan base-package="com.study" use-default-filters="false"><context:include-filter type="annotation"expression="org.springframework.stereotype.Controller"/></context:component-scan><context:component-scan base-package="com.study"><context:exclude-filter type="annotation"expression="org.springframework.stereotype.Controller"/></context:component-scan>
基于注解方式实现属性注入
@Autowired
:根据属性类型进行自动装配
1、把 service 和 dao 对象创建,在 service 和 dao 类添加创建对象注解
UserService
@Servicepublic class UserService {public void add() {System.out.println("UserService调用了add.......");userDao.add();}}
UserDaoImpl
@Repositorypublic class UserDaoImpl implements UserDao {@Overridepublic void add() {System.out.println("dao add.........");}}
2、在 service 注入 dao 对象,在 service 类添加 dao 类型属性,在属性上面使用注解
@Servicepublic class UserService {//定义dao类型属性//不需要添加set方法//添加注入属性注解@Autowired //根据类型注入private UserDao userDao;public void add() {System.out.println("UserService调用了add.......");userDao.add();}}
测试
@Qualifier
:根据名称进行注入
这个@Qualifier
注解的使用,和上面@Autowired
一起使用
@Autowired
是根据 属性类型来注入,但如果有多个相同类型的bean,使用这个注解就麻烦了,比如接口的实现类
因此,使用 @Qualifier
通过名称(注解设置的 value) 就可以很好的解决这个问题
UserDaoImpl
//默认的value是 类的名称(第一个字母小写)@Repository(value = "userDaoImpl1")public class UserDaoImpl implements UserDao {@Overridepublic void add() {System.out.println("dao add.........");}}
UserService
@Servicepublic class UserService {//定义dao类型属性//不需要添加set方法//添加注入属性注解@Autowired //根据类型注入@Qualifier(value = "userDaoImpl1") //指定valueprivate UserDao userDao;
@Resource
:可以根据类型注入,可以根据名称注入
类型注入
@Resourceprivate UserDao userDao;
名称注入
@Resource(name = "userDaoImpl1")private UserDao userDao;
@Value
:注入普通类型属性
@Value("张三")private String name;
完全注解开发
1、创建配置类,替代 xml 配置文件
SpringConfig
@Configuration //作为配置类,替代xml配置文件@ComponentScan(basePackages = "com.study.spring5")public class SpringConfig {}
UserService
@Servicepublic class UserService {@Value("张三")private String name;@Resource(name = "userDaoImpl1")private UserDao userDao;public void add() {System.out.println("UserService调用了add.......");userDao.add();}}
测试
@Testpublic void TestService() {//加载配置类ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);UserService userService = context.getBean("userService", UserService.class);userService.add();}