二、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. CC_CALLBACK原理及应用

    http://my.oschina.net/u/555701/blog/219844 c++ 11 基础 :     std::function 类模版 std::function是一种通用.多态的函 ...

  2. ecshop如何去除后台左侧云服务中心菜单

    介绍一下如何去除后台云服务中心菜单: 打开admin/templates/menu.htm,把539行的 document.getElementById("menu-ul").in ...

  3. 如何关闭log4j中配置的spring或者hibernate的日志信息

    通常在建立一个web项目的时候,我们通常需要为其配置日志,以便了解启动过程中发生了什么,如果启动过程中发生了错误,则可以很方便的查看错误的信息,但是在项目部署到服务器上时,打印日志信息,需要耗费大量的 ...

  4. iOS 定时器Timer常见问题

    最近有朋友问我使用NStimer遇见与ScrollView并存时存在主线程阻塞的问题,自己总结几种解决方法: 问题原因: 一般定时器timer都会被以默认模式default添加到主线程的runloop ...

  5. 获利能力分析COPA的BAPI:BAPI_COPAACTUALS_POSTCOSTDATA 通过增强返回凭证号

    用这个BAPI:BAPI_COPAACTUALS_POSTCOSTDATA 记录销售成本的时候,发现不能return生产的co凭证号,利用内存应该是最好的方法. SCN上的帖子:https://blo ...

  6. linux内核编译步骤

    国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...

  7. 如何使用Linux通用后门(转zafe)

    特别提示:仅用于安全测试和教学,禁止非法用途. 标题党了,呵呵 其实就是个ssh后门,基本可以不用看内核版本,很简单,为照顾新手! ********************************** ...

  8. iOS UITabBarItem 选中图的颜色,设置UIimage的渲染模式

    UITbarController之前有在这篇文章讲解:http://www.cnblogs.com/niit-soft-518/p/4447940.html 如果自定义了UITabBarItem的图片 ...

  9. iOS开发笔记系列-基础1(数据类型与表达式)

    学习iOS开发快两年了,去年完成MagViewer之后就因为公司的其他业务繁重,除了维护这个应用之外,只是断断续续地自己做一些实验开发,没有再发布新的应用,这里想整理一下学习过程中的笔记,以便加深印象 ...

  10. HDU 5112 A Curious Matt 水题

    A Curious Matt Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid ...