二、Spring的核心之IoC(Inversion of Control 控制反转)

1、IoC是什么?

回顾:连接池原理中的使用。

注意:我们在连接池原理中是使用构造函数注入的,当然还可以通过提供set方法实现注入。

      

2、Spring容器

Spring容器简单理解就是用于存放对象的。

3、Spring的IoC入门

3.1、建立一个java工程

3.2、导入Spring的核心jar包

3.3、建立一个XML配置文件

 <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">
</beans>

注意:现在xml文件用什么名字无所谓。

关于spring的xml文件没有提示的原因和解决办法,与struts2和hibernate中相同。只是引入的约束前两个是dtd,而spring引入的schema约束。

3.4、资源交给Spring容器管理

 <!-- 把持久层和业务层的创建都交给spring来管理
bean元素用于配置程序中可重用的组件。包括持久层,业务层以及表现层动作类
id属性指定的是spring容器中的key
class属性指定的就是类的全名称
spring容器在创建时,会读取配置文件,创建一个容器(map),把id作为key,把class属性创建的对象作为value,存入容器中 在加载配置文件时,会反射创建类对象。调用的默认无参的构造函数
-->
<bean id="userDao" class="cn.itcast.dao.impl.UserDaoForMySQLImpl"></bean> <bean id="userService" class="cn.itcast.service.impl.UserServiceImpl">
<!-- 在service中,注入dao -->
<property name="userDao" ref="userDao"></property>
</bean>

3.5、Spring容器的初始化及资源的获取

 public static void main(String[] args) {
/*
* 1.加载配置文件,用于创建spring的容器(map)
* ClassPathXmlApplicationContext:表示配置文件在类路径下
* FileSystemXmlApplicationContext():当配置文件不在类路径下,而是在磁盘上时,使用此类加载。
*/
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
//从容器中获取需要的对象:根据key取value
// IUserDao userDao = (IUserDao) ac.getBean("userDao");
// System.out.println(userDao);
IUserService userService = (IUserService) ac.getBean("userService");
System.out.println(userService);
userService.saveUser();
}

4、Spring中API的体系结构

4.1、核心接口和类

BeanFactory:它使用的是延迟加载思想。当我们需要用bean时,才去创建对象。

ApplicationContext:它继承自BeanFactory接口,还继承了很多其他接口。功能比BeanFactory强大。它用的不是延迟加载思想,而是在加载配置文件时就创建了。(推荐)

FileSystemXmlApplicationContext:配置文件在本地磁盘上,使用该类加载。

ClassPathXmlApplicationContext :配置文件在classpath中,使用此类加载。

5、基于XML的spring的IoC配置

5.1、Spring实例化bean的方式

调用默认的构造方法 (推荐)

 <!-- 把持久层和业务层的创建都交给spring来管理
bean元素用于配置程序中可重用的组件。包括持久层,业务层以及表现层动作类
id属性指定的是spring容器中的key
class属性指定的就是类的全名称
spring容器在创建时,会读取配置文件,创建一个容器(map),把id作为key,把class属性创建的对象作为value,存入容器中 需要掌握:在加载配置文件时,会反射创建类对象。调用的默认无参的构造函数。如果没有提供无参构造的情况下,是不能实例化bean对象的
-->
<bean id="userDao" class="cn.itcast.dao.impl.UserDaoForMySQLImpl"></bean> <bean id="userService" class="cn.itcast.service.impl.UserServiceImpl"></bean>

5.2、Bean的作用范围

 <!-- Bean的作用范围
scope属性:
取值:
singleton:单例(默认值)
prototype:多例
request:请求范围
session:会话范围
global-session:集群的会话范围。
-->
<bean id="userBean" class="cn.itcast.bean.UserBean1" scope="prototype">
</bean>

5.3、Bean的生命周期方法

 /**
* 模拟一个Bean
* @author zhy
*
*/
public class UserBean { //实例化
public UserBean(){
System.out.println("实例化:大爷来也!");
}
//初始化
public void init(){
System.out.println("初始化:大爷准备好了");
}
//销毁
public void destroy(){
System.out.println("销毁:老夫休矣!");
} public void saveUser(){
System.out.println("业务方法:老夫只劫财不劫色");
}
}
 <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的生命周期
bean默认情况下是单例的,但是没有执行销毁方法。
bean:出生 活着 死亡
出生:在使用立即加载方式,spring容器一创建,bean对象就已经都创建好了。实例化bean和初始化bean就都执行了。
活着:spring容器还在,bean对象就一直在。
死亡:spring容器如果没了,bean对象也就消亡了。
-->
<bean id="userBean" class="cn.itcast.bean.UserBean" init-method="init" destroy-method="destroy"></bean>
</beans>

注意:当非单例时,初始化方法正常执行,但是销毁方法就不会执行了。

5.4、依赖注入

a、构造器注入:通过传参数

 <!-- 第一种方式:是通过构造函数注入
使用construtor-arg
常用属性:
index:指定的是参数出现在构造函数中的索引
type:指定参数在构造函数中的数据类型
name:指定参数在构造函数中的名称 *****
以上三个都是在指定:给谁注入 value:注入基本数据类型或者String类型的值
ref:注入的是其他bean类型的值
以上两个都是在指定:注入的值 当在定义bean时,使用了constructor-arg元素,则在bean元素中有几个constructor-arg,就需要提供对应参数列表的构造函数
-->
<bean id="userBean" class="cn.itcast.bean.UserBean1">
<constructor-arg name="name" value="test" ></constructor-arg>
<constructor-arg name="age" value="18"></constructor-arg>
<constructor-arg name="birthday" ref="now" ></constructor-arg>
</bean>

b、属性注入:推荐

 <!-- 第二种方式:是通过属性的set方法注入
需要使用的元素是:property
属性:
name:写的是set方法后面的部分,并且首字母转小写。
ref:注入的其他Bean类型的值
value:注入的是基本类型或者String类型的值
-->
<bean id="userBean2" class="cn.itcast.bean.UserBean2">
<property name="name" value="test" ></property>
<property name="age" value="18"></property>
<property name="birthday" ref="now"></property>
</bean>

c、p名称空间

 <beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
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">
<!-- 使用p名称空间注入
1、导入P名称空间:xmlns:p="http://www.springframework.org/schema/p"
2、在bean元素中使用p名称空间
p:属性名称。
属性名称指的是set方法后面的部分。
每个属性都有两个赋值方式:
p:属性名称
p:属性名称-ref
-->
<bean id="userBean4" class="cn.itcast.bean.UserBean4" p:name="test" p:age="20" p:birthday-ref="now"></bean> <bean id="now" class="java.util.Date"></bean>

d、SpEL(Spring Expression Lanaguage)

 <!-- 使用Spring中EL表达式。SpringEL 目前定位:了解
${now}就是SPring的EL表达式
-->
<bean id="userBean3" class="cn.itcast.bean.UserBean3">
<property name="name" value="test" ></property>
<property name="age" value="18"></property>
<property name="birthday" value="#{now}"></property>
</bean>

e、注入集合数据

 <!-- 注入集合数据
如果是对象集合数据,list结构的,可以使用如下三个元素:
array
list
set
如果是map结构的,可以使用如下四个元素
map:
map的子元素是entry
props
props的子元素是prop
只要结构相同,元素可以互换。
-->
<bean id="userBean5" class="cn.itcast.bean.UserBean5">
<!-- 给数组注入值 -->
<property name="myStrs">
<list>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
</list>
</property>
<!-- 给List集合注入值 -->
<property name="myList">
<set>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
</set>
</property>
<!-- 给Set集合注入值 -->
<property name="mySet">
<array>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
</array>
</property>
<!-- 给map注入数据 -->
<property name="myMap">
<props>
<prop key="testA">AAA</prop>
<prop key="testB">BBB</prop>
<prop key="testC">CCC</prop>
</props>
</property>
<!-- 给properties注入数据 -->
<property name="myProps">
<map>
<entry key="AAA">
<value>testA</value>
</entry>
<entry key="BBB" value="testB"></entry>
<entry key="CCC">
<value>testC</value>
</entry>
</map>
</property>

5.5、团队开发:多个Spring配置文件

a、一次加载多个配置文件

 public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("bean1.xml","bean2.xml");
//获取bean对象
UserBean1 bean1 = (UserBean1)ac.getBean("userBean1");
bean1.saveUser(); UserBean2 bean2 = (UserBean2)ac.getBean("userBean2");
bean2.saveUser();
}

b、基于主从配置文件

 <!-- Spring的多配置文件
引入其他的配置
-->
<import resource="bean1.xml"/>
<import resource="bean2.xml"/>

c、注意事项

同一个配置文件中不能出现bean元素id属性取值相同的:

不同文件中bean元素id属性取值相同时,有加载顺序

使用bean的name属性获取bean对象(了解就行)

6、基于注解的spring的IoC配置

6.1、注解的使用前提

a、引入context的名称空间

b、指定要扫描的包

c、在Bean上面加入@Component注解

 @Component("userBean")
//就相当于在配置文件中配置<bean id="userBean" class="cn.itcast.bean.UserBean" />
public class UserBean { @Value(value="test")
private String name; public void saveUser(){
System.out.println("业务方法:老夫只劫财不劫色");
System.out.println(name);
}
}

b、@Component的衍生注解@Controller@Service@Repository

作用:和@Component作用一样,让Spring容器管理(实例化)当前的bean。

属性: value:指定bean的名称。默认值是当前类的简单类名首字母小写

特点:在三成架构中,每个注解对应一层,使语义更加明确。

@Controller一般用在表现层,比如struts2action

@Service一般用在业务层,比如Service实现

@Repository一般用在持久层,比如Dao实现

 @Repository("userDaoForMySQL")
public class UserDaoForMySQLImpl implements IUserDao { public void saveUser() {
System.out.println("MySQL:保存了用户");
} public void deleteUser() {
System.out.println("MySQL:删除了用户");
} }
@Service("userService")
public class UserServiceImpl implements IUserService { public void saveUser() {
System.out.println("UserServiceImpl的savaUser方法执行了");
userDao.saveUser();
} public void deleteUser() {
userDao.deleteUser();
} }
@Controller("userAction")
public class UserAction { public String saveUser(){
System.out.println("UserAction的savaUser方法执行了");
userService.saveUser();
return null;
}
}

c、@Autowired

作用:自动按类型注入需要的对象。当使用了该注解时,setter就不是必须的了。

属性:

required:是否必须注入成功。默认值是true。

true:必须注入成功,如果出现注入失败,抛出异常。

false:不一定注入成功,不抛异常。

注意事项:

一个Service接口:IBookService

两个Service实现:BookServiceImpl1  BookServiceImpl2

由于@Autowired是自动按类型注入,当使用接口类型时,就看变量的名称,如果变量名称是bookServiceImpl1,则使用BookServiceImp1这个实现类,

如果变量名是bookServiceImpl2,则使用BookServiceImpl2这个实现类。如果没有符合规范的名称(类名首字母小写),则报错。

到底注入哪个实现类:

@Autowried

private BookService bookServiceImpl1;//注入BookServiceImpl1

@Autowried

private BookService bookServiceImpl2;//注入BookServiceImpl2

@Autowried

private BookService bookService;//注入失败

d、@Value

作用:注入基本类型和String。

属性:value:SpEL表达式,要注入的值

e、@Qualifier

作用:要配合@Autowried来一起使用,通过它指定要注入的bean的名称。按类型注入失效了。

属性:value:要注入的bean的名称

f、@Resource

作用:如同@Autowire和@Qualifier,是规范JSR-250中定义的(JCP)。通过指定bean的名称注入对象。

属性: name:要注入的bean的名称

g、@PostConstruct(了解)

作用:用在初始化方法上。生命周期有关

h、@PreDestroy(了解)

作用:用在销毁方法上。生命周期有关

i、@Configuration和@Bean(了解)

作用:@Configuration指定当前类为配置类,用于加载@Bean的定义。@Bean用于定义bean的名称,用法是@Bean(name="beanName")

注意:该类要被设置在注解自动扫描对应的包下。

6.3、Spring中使用单元测试

a、导入jar包:

spring-test-3.2.0.RELEASE.jar

b、设置Junit运行器和Spring配置文件

 /**
* Spring整合Junit
* 1、导入junit的jar包。导入spring整合junit的jar包
* 2、要替换运行器(其实就是测试用的main函数),换成spring框架提供的,因为只有spring框架提供的才能支持spring。
* 3、告知新运行器,spring的配置文件所在的位置
* @author zhy
*
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:bean.xml"})
public class UserBeanTest { @Autowired
private UserBean userBean; @Test
public void testSaveUser(){
userBean.saveUser();
}
}

Java实战之03Spring-02Spring的核心之IoC的更多相关文章

  1. [转载] JAVA面试题和项目面试核心要点精华总结(想进大公司必看)

    JAVA面试题和项目面试核心要点精华总结(想进大公司必看) JAVA面试题和项目面试核心要点精华总结(想进大公司必看)

  2. 「小程序JAVA实战」springboot的后台搭建(31)

    转自:https://idig8.com/2018/08/29/xiaochengxujavashizhanspringbootdehoutaidajian31/ 根据下面的图,我们来建立下对应的sp ...

  3. Java中对象的生与灭- 核心篇

    前言 大家好啊,我是汤圆,今天给大家带来的是<Java中对象的生与灭- 核心篇>,希望对大家有帮助,谢谢 文章纯属原创,个人总结难免有差错,如果有,麻烦在评论区回复或后台私信,谢啦 简介 ...

  4. Java实战:教你如何进行数据库分库分表

    摘要:本文通过实际案例,说明如何按日期来对订单数据进行水平分库和分表,实现数据的分布式查询和操作. 本文分享自华为云社区<数据库分库分表Java实战经验总结 丨[绽放吧!数据库]>,作者: ...

  5. Spring核心思想Ioc和Aop (面试)

    Spring核心思想Ioc和Aop (面试) 注意: Ioc和Aop并不是Spring提出的,在Spring之前就已经存在,Spring只是在技术层面给这两个思想做了非常好的实现. 1 Ioc 1.1 ...

  6. Java Spring Boot VS .NetCore (三)Ioc容器处理

    Java Spring Boot VS .NetCore (一)来一个简单的 Hello World Java Spring Boot VS .NetCore (二)实现一个过滤器Filter Jav ...

  7. Spring 核心之IOC 容器

    核心概念: IOC(Inversion of Control)控制反转:所谓控制反转,就是把原先我们代码里面需要实现的对象创建.依赖的代码,反转给容器来帮忙实现. DI(Dependency Inje ...

  8. Java实战之03Spring-03Spring的核心之AOP(Aspect Oriented Programming 面向切面编程)

    三.Spring的核心之AOP(Aspect Oriented Programming 面向切面编程) 1.AOP概念及原理 1.1.什么是AOP OOP:Object Oriented Progra ...

  9. 添物零基础到大型全栈架构师 Java实战及解析(实战篇)- 概述

    ​ 实战篇是在基础之上,进一步提升的内容.通过实战篇可以深入理解Java相关框架和库的使用,能够独立开发小模块,或者按照架构师的指导进行代码编写和完善. 主要讲解核心框架和库的使用和使用场景介绍.通过 ...

随机推荐

  1. Packetbeat协议扩展开发教程 一

    原文链接:http://elasticsearch.cn/article/48 Packetbeat(https://www.elastic.co/products/beats/packetbeat) ...

  2. JavaScript要点(十三) HTML DOM EventListener

    addEventListener() 方法 <body> <p>该实例使用 addEventListener() 方法在按钮中添加点击事件. </p> <bu ...

  3. 升级SUSE Linux内核的完整步骤!

    http://blog.sina.com.cn/s/blog_491529d60100061h.html 安装完SLED 10后发现仍然有“热启动网络不通”的问题,原因是内核版本较低,于是升级到2.6 ...

  4. 创建性能监视器(logman)

    在本地计算机上抓取性能信息 Logman.exe create counter Perf-1Second -f bincirc -max 500 -c "\Processor(*)\% Pr ...

  5. IOS开发之类和对象

    IOS开发之类和对象 OC和Java一样都是一种面向对象的语言,从今天開始我和大家一起来系统学习这样的面向对象的语言oc,欢迎大家什么问题和我一起探讨和学习. OC定义类有两个步骤:1.接口部分(通俗 ...

  6. C++容器类对象函数參数问题

    总之中的一个句话:容器类对象作为函数參数,与整数类型作为函数參数的传递特性同样. 验证程序 #include "stdafx.h" #include <iostream> ...

  7. IOS笔记 #pragma mark的用法

    简单的来说就是为了方便查找和导航代码用的. 下面举例如何快速的定位到我已经标识过的代码. #pragma mark 播放节拍器 - (void) Run:(NSNumber *)tick { //.. ...

  8. J2EE的13个规范之(三) Servlet简单介绍

    Servlet是一种server端脚本,它是一个特殊的Java类,继承自HttpServlet.开发中主要用于处理和响应client的请求. Servlet在容器中执行,事实上例的和销毁创建由容器进行 ...

  9. Database and models

    Database and models The database Now that we have the Album module set up with controller action met ...

  10. SQL Abstraction and Object Hydration

    SQL Abstraction and Object Hydration In the last chapter, we introduced database abstraction and a n ...