Spring入门01-IOCDI
目录
一、学习导图
二、Spring 框架概念
三、基本环境搭建
四、SpringIOC容器Bean对象的实例化的模拟实现
什么是IOC?
(1)定义bean属性对象
(2)添加dom4j坐标依赖
(3)自定义spring.xml配置文件
(4)定义bean工厂接口
(5)测试
五、配置文件加载
六、IOC容器Bean对象实例化
Spring三种实例化Bean的方式比较
七、Spring IOC 注入
注入方式的选择
七、Spring IOC 自动装配(注入)
注解方式注入 Bean
@Resource注解
@Autowired注解
八、Spring IOC 扫描器
九、Bean的作用域与生命周期
1.Bean的作用域
(1)lazy-init属性(懒加载)
lazy-init属性为什么要设置为false?
(2)Scope属性:
1.singleton:单例作用域(默认)
什么对象适合作为单例对象?(什么对象适合交给IOC容器实例化?)
2.prototype:原型作用域
2.Bean的生命周期
一、学习导图

二、Spring 框架概念
Spring 是众多开源 java 项目中的一员,基于分层的 javaEE 应用一站 式轻量级开源框架,主要核心是 IOC (控制反转 / 依赖注入)与 AOP(面向切面)两大技术,实现项目在开发过程中的轻松解耦, 提高项目的开发效率。 在项目中引入 Spring 立即可以带来下面的好处 降低组件之间的耦合度, 实现软件各层之间的解耦。可以使用容器提供的众多服务,如:事务管理服务、消息服务等等。当我们使用容器管理事务时, 开发人员就不再需要手工控制事务。 也不需处理复杂的事务传播。 容器提供单例模式支持,开发人员不再需要自己编写实现代码。 容器提供了AOP 技术,利用它很容易实现如权限拦截、运行期监控等功能。
三、基本环境搭建
1.新建Maven项目:模板quick-start
2.配置pom文件
4.0.0 com.msb Spring01 1.0-SNAPSHOT jar Spring01 http://maven.apache.org UTF-8 1.8 1.8 junit junit 4.12 test org.springframework spring-context 5.2.4.RELEASE
3.编写Bean对象,如dao层、service层对象。
4.添加spring配置文件
在项目的src下创建resources并标记为Resources Root
5.测试类中加载配置文件
6.启动
public class Starter01 {public static void main(String[] args) {//得到spring的上下文环境ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");//通过id属性得到指定的bean对象UserService userService = (UserService) ac.getBean("userService");//调用实例化好的javabean对象的方法userService.test();//通过id属性得到指定的bean对象UserService02 userService02 = (UserService02) ac.getBean("userService02");//调用实例化好的javabean对象的方法userService02.test();}
} 四、SpringIOC容器Bean对象的实例化的模拟实现
什么是IOC?
解释1:创建对象的权利,或者是控制的位置,由JAVA代码转移到spring容器,由spring的容器控制对象的创建,就是控制反转。spring创建对象时,会读取配置文件中的信息,然后使用反射给我们创建好对象之后在容器中存储起来,当我们需要某个对象时,通过id获取对象即可,不需要我们自己去new。
一句话:创建对象交给容器
解释2:Spring框架管理这些Bean的创建工作,即由用户管理Bean转变为框架管理Bean,这个就叫 控制反转 - Inversion of Control (IoC)
部分引用自什么是控制反转(IOC)? - 知乎
思路:
- 定义Bean 工厂接口,提供获取bean方法
- 定义Bean工厂接口实现类,解析配置文件,实例化Bean对象
- 实现获取 Bean 方法
(1)定义bean属性对象
/*** Bean属性对象* 用来存放配置文件中bean标签对应的id和class属性值*/
public class MyBean {private String id; //bean标签的id属性值private String clazz; //bean标签的class属性值public MyBean() {}public MyBean(String id, String clazz) {this.id = id;this.clazz = clazz;}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getClazz() {return clazz;}public void setClazz(String clazz) {this.clazz = clazz;}
} (2)添加dom4j坐标依赖
dom4j dom4j 1.6.1 jaxen jaxen 1.1.6 (3)自定义spring.xml配置文件
(4)定义bean工厂接口
public interface MyFactory {//通过id属性值获取对象public Object getBean(String id);
} 实现类:
/*** 模拟Spring的实现* 1. 通过带参构造器得到对应的配置文件* 2. 通过dom4j解析配置文件(xml文件),得到List集合(存放bean标签的id和class属性值)* 3. 通过反射得到对应的实例化对象,放置在Map对象 (遍历List集合,通过获取对应的class属性,利用Class.forName(class).newIntance())* 4. 通过id属性值获取指定的实例化对象*/
public class MyClassPathXmlApplicationContext implements MyFactory {private List beanList; // 存放从配置文件中获取到的bean标签的信息(MyBean代表的就是每一个bean标签)private Map beanMap = new HashMap<>(); // 存放实例化好的对象,通过id获取对应的对象/* 通过带参构造器得到对应的配置文件 */public MyClassPathXmlApplicationContext(String fileName) {/* 通过dom4j解析配置文件(xml文件),得到List集合 */this.parseXml(fileName);/* 通过反射得到对应的实例化对象,放置在Map对象 */this.instanceBean();}/*** 通过dom4j解析配置文件(xml文件),得到List集合* 1. 获取解析器* 2. 获取配置文件的URL* 3. 通过解析器解析配置文件(xml文件)* 4. 通过xpath语法解析,获取beans标签下的所有bean标签* 5. 通过指定的解析语法解析文档对象,返回元素集合* 6. 判断元素集合是否为空* 7. 如果元素集合不为空,遍历集合* 8. 获取bean标签元素的属性 (id和class属性值)* 9. 获取MyBean对象,将id和class属性值设置到对象中,再将对象设置到MyBean的集合中** @param fileName*/private void parseXml(String fileName) {
// 1. 获取解析器SAXReader saxReader = new SAXReader();
// 2. 获取配置文件的URLURL url = this.getClass().getClassLoader().getResource(fileName);try {
// 3. 通过解析器解析配置文件(xml文件)Document document = saxReader.read(url);
// 4. 通过xpath语法解析,获取beans标签下的所有bean标签XPath xPath = document.createXPath("beans/bean");
// 5. 通过指定的解析语法解析文档对象,返回元素集合List elementList = xPath.selectNodes(document);
// 6. 判断元素集合是否为空if (elementList != null && elementList.size() > 0) {// 实例化beanListbeanList = new ArrayList<>();
// 7. 如果元素集合不为空,遍历集合for (Element el : elementList) {
// 8. 获取bean标签元素的属性 (id和class属性值)String id = el.attributeValue("id");//id属性值String clazz = el.attributeValue("class");//class属性值
// 9. 获取MyBean对象,将id和class属性值设置到对象中,再将对象设置到MyBean的集合中MyBean myBean = new MyBean(id, clazz);beanList.add(myBean);}}} catch (DocumentException e) {e.printStackTrace();}}/*** 通过反射得到对应的实例化对象,放置在Map对象* 1. 判断对象集合是否为空,如果不为空,则遍历集合,获取对象的id和calss属性* 2. 通过类的全路径名 反射 得到实例化对象 Class.forName(class).newInstance()* 3. 将对应的id和实例化好的bean对象设置到map对象中*/private void instanceBean() {
// 1. 判断对象集合是否为空,如果不为空,则遍历集合,获取对象的id和calss属性if (beanList != null && beanList.size() > 0) {for (MyBean bean : beanList) {String id = bean.getId();String clazz = bean.getClazz();try {
// 2. 通过类的全路径名 反射 得到实例化对象 Class.forName(class).newInstance()Object o = Class.forName(clazz).newInstance();
// 3. 将对应的id和实例化好的bean对象设置到map对象中beanMap.put(id, o);} catch (Exception e) {e.printStackTrace();}}}}/*** 通过id获取对应的map对象中的value(实例化好的bean对象)** @param id* @return*/@Overridepublic Object getBean(String id) {Object obj = beanMap.get(id);return obj;}
} (5)测试
public class App {public static void main(String[] args) {//得到工厂的实现类MyFactory factory = new MyClassPathXmlApplicationContext("spring.xml");//得到对应的实例化对象UserDao userDao = (UserDao) factory.getBean("userDao");UserService userService = (UserService) factory.getBean("userService");userDao.test();userService.test();UserDao userDao02 = (UserDao) factory.getBean("userDao");System.out.println(userDao==userDao02);}
} 五、配置文件加载
- 根据相对路径加载资源(常规)
- 根据绝对路径加载资源(了解)
- 多配置文件加载,可变参数,传入多个文件名
- 多配置文件加载,总的配置文件import其他文件,只需要加载总文件即可
六、IOC容器Bean对象实例化
- 构造器实例化
- 静态工厂实例化(了解)
- 实例化工厂实例化(了解)
配置:
工厂: public class StaticFactory { //静态/*** 定义对应的静态方法* @return*/public static TypeService createService(){// 实例化前可以做事return new TypeService();}
}public class InstanceFactory { //实例化public TypeController createTypeController(){return new TypeController();}
} 测试: public static void main(String[] args) {/*** 返回的全是单例*/BeanFactory factory = new ClassPathXmlApplicationContext("spring02.xml");//构造器实例化TypeDao typeDao = (TypeDao) factory.getBean("typeDao");typeDao.test();System.out.println(typeDao);System.out.println(factory.getBean("typeDao"));//静态工厂实例化TypeService typeService = (TypeService) factory.getBean("typeService");typeService.test();// 实例化工厂实例化TypeController typeController = (TypeController)factory.getBean("typeController");typeController.test();} 注意:当我们指定Spring使用静态工厂方法来创建Bean实例时,Spring将先解析配置文件,并根据配置文件指定的信息,通过反射调用静态工厂类的静态工厂方法,并将该静态工厂方法的返回值作为Bean实例,在这个过程中,Spring不再负责创建Bean实例,Bean实例是由用户提供的静态工厂方法提供的。
Spring三种实例化Bean的方式比较
方式一: 通过 bean 的缺省构造函数创建 ,当各个 bean 的业务逻 辑相互比较独立的时候或者和外界关联较少的时候可以使用。 方式二:利用静态 factory 方法创建,可以统一管理各个 bean 的 创建,如各个bean 在创建之前需要相同的初始化处理,则可用这个factory 方法先进行统一的处理等等。 方式三:利用实例化 factory 方法创建,即将 factory 方法也作为了业务bean 来控制, 1 可用于集成其他框架的 bean 创建管理方法,2 能够使 bean 和 factory 的角色互换。 开发中项目一般使用一种方式实例化 bean ,项目开发基本采用第 一种方式,交给 Spring 托管,使用时直接拿来使用即可。另外两种 了解。七、Spring IOC 注入
Spring 支持的注入方式共有四种: set 注入、构造器注入、静态工厂注入、实例化工厂注入。 set 方法注入: 属性字段需要提供 set 方法 四种方式,推荐使用 set 方法注入北京 上海 深圳
西藏 新疆 云南 山东 河北 河南
注入方式的选择
重点掌握 set 注入和构造器注入,工厂方式了解即可。实际开发 中基本使用 set 方式注入 bean 。 p 名称空间的使用: spring2.5 以后,为了简化 setter 方法属性注入,引用 p 名称空间的 概念,可以将子元素,简化为元素属性配置。
七、Spring IOC 自动装配(注入)
注解方式注入 Bean
对于 bean 的注入,除了使用 xml 配置以外,可以使用注解配置。 注解的配置,可以简化配置文件,提高开发的速度,使程序看上去更简洁。对于注解的解释,Spring 对于注解有专门的解释器,对定义的注解进行解析,实现对应bean 对象的注入。通过 反射技术实现。
参考:<context:annotation-config/>的作用_tiny-dong的博客-CSDN博客
@Resource注解
@Resource注解实现自动注入 (反射)
1. 注解默认通过属性字段名称查找对应的bean对象(属性字段名称与bean标签的id属性值一致)
2. 如果属性字段名称不一样,则会通过类型(Class)类型
3. 属性字段可以提供set方法 也可以不提供
4. 注解可以声明在属性字段上 或 set方法级别
5. 可以设置注解的name属性,name属性值要与bean标签的id属性值一致(如果设置了name属性,则会按照name属性查询bean对象)
6. 当注入接口时,如果接口只有一个实现类,则正常实例化;如果接口有多个实现类,则需要使用name属性指定需要被实例化的bean对象
@Autowired注解
@Autowired注解实现自动化注入
1. 注解默认使用类型(Class类型)查找bean对象,与属性字段名称没有关系
2. 属性字段可以提供set方法 也可以不提供
3. 注解可以声明在属性级别 或 set方法级别
4. 如果想要通过指定名称查找bean对象,需要结合@Qualifier使用(通过设置value属性值查找,value属性值要bean标签的id属性值保持一致)
八、Spring IOC 扫描器
实际的开发中, bean 的数量非常多,采用手动配置 bean 的方式已无法满足生产需要,Spring 这时候同样提供了扫描的方式,对扫描到的bean 对象统一进行管理,简化开发配置,提高开发效率。
九、Bean的作用域与生命周期
1.Bean的作用域
(1)lazy-init属性(懒加载)
如果设置为true,表示懒加载,容器在启动时,不会实例化bean对象,在程序调用时才会实例化;
如果设置false(默认),表示不懒加载,容器启动则实例化bean对象。
lazy-init属性为什么要设置为false?
- 可以提前发现潜在的配置问题
- Bean对象在启动时就设置在单例缓存池中,使用时不需要再去实例化bean对象,提高程序运行效率
(2)Scope属性:
1.singleton:单例作用域(默认)
默认情况下,我们从 Spring 容器中拿到的对象均是 单例 的,对于 bean的作用域类型如下:
注意:
- 默认懒加载是false即Spring容器启动时实例化。如果等于true作用是指Spring容器启动的时候不会去实例化这个bean, 而是在程序调用时才去实例化。
- 默认单例:被管理的Bean只会在IOC容器中存在一个实例,对于所有获取该Bean的操作,Spring容器将只返回同一个Bean。
- 容器在启动的情况下就实例化所有singleton 的 bean对象,并缓存与容器中。
总结:Spring IOC容器在启动时,会将所有在singleton作用域中的bean对象实例化,并设置到单例缓存池中。
配置如下:
什么对象适合作为单例对象?(什么对象适合交给IOC容器实例化?)
无状态的对象(不存在改变当前对象状态的成员变量)比如:controller层、service层、dao层。
什么是无状态或状态不可改变的对象? 实际上对象状态的变化往往均是由于属性值得变化而引起的,比如user类姓名属性会有变化,属性姓名的变化一般会引起 user 对象状态的变化。对于我们的程序来说,无状态对象没有实例变量的存 在,保证了线程的安全性, service 层业务对象即是无状态对象,线程安全的。2.prototype:原型作用域

通过scope="prototype" 设置bean的类型 ,每次向Spring容器请求获取Bean都返回一个全新的Bean,相对于"singleton"来说就是不缓存Bean,每次都是一个根据Bean定义创建的全新Bean。
总结:Spring IOC容器在启动时,不会将bean对象实例化设置到单例缓存池中,每次实例化对象都会创建一个新的实例。
2.Bean的生命周期
在Spring中,Bean的生命周期包括Bean的定义、初始化、使用和销毁4个阶段。
Bean的定义
在配置文件中定义bean,通过bean标签定义对应bean对象。
Bean的初始化
IOC容器启动时,自动实例化Bean对象
1. 在配置文档中通过指定 init-method 属性来完成。
2. 实现 org.springframework.beans.factory.InitializingBean 接口。
Bean的使用
1. 使用 BeanFactory对象
2. 使用 ApplicationContext对象
Bean的销毁
步骤一:通过 AbstractApplicationContext 对象,调用其close方法实现bean的销毁过程
// 通过 AbstractApplicationContext 对象,调用其close方法实现bean的销毁过程
AbstractApplicationContext ac = new ClassPathXmlApplicationContext("spring03.xml");
System.out.println("销毁前");
ac.close();
System.out.println("销毁后");
步骤二:在配置文件中指定对应销毁的方法 destroy-method
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
