二、spring的IoC
IoC的基本认识
Inversion of Control:控制反转,就是将对象的创建权反转交给spring
IoC的好处
传统方式的程序编写,底层的实现切换了,需要修改源代码
使用spring之后,实现类都交给IoC容器中的BeanFactory来管理,通过工厂+反射+配置文件来实现程序的解耦合
<bean id="user" class="com.qf.demo.User">
class BeanFactory{
public static Object getBean(String id) {//id:bean标签的id
Class clazz = Class.forName(className);//className:bean标签的class
return clazz.newInstance();
}
}
IoC和DI
<bean id="user" class="com.qf.demo.User">
<property name="id" value="1"/>
<property name="name" value="qf"/>
<property name="age" value="18"/>
</bean>IoC:控制反转,就是将对象的创建权反转给spring
DI:依赖注入,前提必须有IoC的环境,然后Spring管理这个类的时候把这个类依赖的属性注入进来
描述:Class A中用到了Class B的对象b,一般情况下,需要在A的代码中显式的new一个B的对象。采用依赖注入技术之后,A的代码只需要定义一个私有的B对象,不需要直接new来获得这个对象,而是通过相关的容器控制程序来将B对象在外部new出来并注入到A类里的引用中。而具体获取的方法、对象被获取时的状态由配置文件(如XML)来指定
Spring的工厂类
- ApplicationContext是新版本spring的工厂类、BeanFactory是老版本spring的工厂类
- ApplicationContext继承了BeanFactory接口
- BeanFactory在调用getBean方法时才会生成类的实例;ApplicationContext在加载配置文件时就会生成类的实例
- ApplicationContext接口有两个实现类
- ClassPathXmlApplicationContext:加载类路径下的配置文件
- FileSystemXmlApplicationContext :加载文件系统下的配置文件
配置spring
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<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 id="user" class="com.qf.demo.User">
<property name="id" value="1"/>
<property name="name" value="qf"/>
<property name="age" value="18"/>
</bean> </beans>
bean配置
bean标签
- 标识
- id:使用了唯一约束;不能使用特殊字符
- name:未使用唯一约束;可以使用特殊字符,例如 /user
- 生命周期
- init-method:bean被初始化时执行的方法
- destroy-method:bean被销毁时执行的方法(bean必须是单例创建的才可以进行工厂关闭,多例的情况下无法工厂关闭)
- 测试,User类中定义两个方法init和destroy
package com.qf.demo; public class User { private Long id;
private String name;
private Integer age; public void setId(Long id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setAge(Integer age) {
this.age = age;
} @Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", age=" + age + "]";
} public User(Long id, String name, Integer age) {
super();
this.id = id;
this.name = name;
this.age = age;
}
public User() {
super();
} public void init() {
System.out.println("初始化----------");
}
public void destroy() {
System.out.println("销毁----------");
}
}applicationContext.xml中配置spring管理User对象时配置init属性和destroy属性
<?xml version="1.0" encoding="UTF-8"?>
<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 id="user" class="com.qf.demo.User" init-method="init" destroy-method="destroy">
<property name="id" value="1"/>
<property name="name" value="qf"/>
<property name="age" value="18"/>
</bean> </beans>测试类
public class TestDemo { @Test
public void test() {
// ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// ApplicationContext类里没有close方法
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
User user1 = (User) context.getBean("user");
System.out.println(user1);
// User user2 = (User) context.getBean("user");
// System.out.println(user2);
context.close();
}
}console输出结果
初始化----------
User [id=1, name=qf, age=18]
销毁----------注:如果bean中配置scope="prototype",测试会发现destroy不执行,即工厂无法close
- 作用域
- scope:bean的作用域属性
- singleton:默认的,spring采用单例模式创建对象
- prototype:spring采用多例模式创建对象
- request:在web项目中使用,spring创建完这个类对象后,将这个对象存入到request中
- session:在web项目中使用,spring创建完这个类对象后,将这个对象存入到session中
- globalSession:在web项目中使用,在porlet环境下,spring创建完这个类对象后,这个对象在其子系统中可以使用;没有porlet环境,相当于session
- scope:bean的作用域属性
- 测试1
- 修改applicationContext.xml的bean配置,配置scope属性
<bean id="user" class="com.qf.demo.User" scope="prototype">
- 测试方法
@Test
public void test() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
User user1 = (User) context.getBean("user");
User user2 = (User) context.getBean("user");
System.out.println(user2 == user1);
} - console输出结果
false
- 结论:采用多例模式创建对象,两次调用getBean方法创建了两个不同的对象
- 修改applicationContext.xml的bean配置,配置scope属性
- 测试2
- 在测试1的基础上修改scope属性值为singleton
- console输出结果
true
- 结论:采用单例模式创建对象,两次调用getBean方法创建了两个相同的对象
- 测试1
Spring的bean管理方式
XML方式:适用于任何场景。结构清晰,便于维护
注解方式:如果类不是自己提供的就不能使用(没办法改源码)。开发更加简单方便
XML方式管理Bean
spring的bean的实例化
- 无参构造方式实例化bean
- 自定义bean
public class TestBean { public TestBean() {
System.out.println("无参构造方式实例化完成");
}
} - 配置bean
<bean id="test" class="com.qf.demo.TestBean"></bean>
- 测试方法
@Test
public void test() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
TestBean test = (TestBean) context.getBean("test");
System.out.println(test);
} - console输出
无参构造方式实例化完成
com.qf.demo.TestBean@635c714a
- 自定义bean
- 静态工厂方式实例化bean
- 创建静态工厂类
package com.qf.demo; public class TestBeanFactory {
public static Bean getBean() {
System.out.println("静态工厂实例化完成");
return new Bean();
}
}
class Bean{ } - 配置bean
<bean id="test" class="com.qf.demo.TestBeanFactory" factory-method="getBean"></bean>
- 创建静态工厂类
- 实例工厂方式实例化bean
- 创建实例工厂类
package com.qf.demo; public class BeanInstance { public Bean getInstance() {
System.out.println("实例工厂方式实例化bean完成");
return new Bean();
}
} - 配置bean
<bean id="instance" class="com.qf.demo.BeanInstance"/>
<bean id="test" factory-bean="instance" factory-method="getInstance"/>
- 创建实例工厂类
属性注入
- 构造方法
- bean类中定义带参数的构造方法
package com.qf.demo; public class User {
private Long id;
private String name;
private Integer age;
private Address address; public User(Long id, String name, Integer age, Address address) {
super();
this.id = id;
this.name = name;
this.age = age;
this.address = address;
}
public User() {
super();
} @Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", age=" + age + ", address=" + address + "]";
}
} - 配置bean
<bean id="address" class="com.qf.demo.Address"></bean>
<!-- 构造方法注入属性值,通过index索引注入 -->
<bean id="user" class="com.qf.demo.User">
<constructor-arg index="0" value="1"/>
<constructor-arg index="1" value="wxf"/>
<constructor-arg index="2" value="24"/>
<!-- 注入的属性值是另一个bean对象:使用ref属性设置 -->
<constructor-arg index="3" ref="address"/>
</bean> <!-- 构造方法注入属性值,通过name参数名称注入 -->
<bean id="user1" class="com.qf.demo.User">
<constructor-arg name="id" value="2"/>
<constructor-arg name="name" value="qf"/>
<constructor-arg name="age" value="18"/>
<constructor-arg name="address" ref="address"/>
</bean>
- bean类中定义带参数的构造方法
- set方法
- bean类中定义属性的setter方法
package com.qf.demo; public class User {
private Long id;
private String name;
private Integer age;
private Address address; public void setId(Long id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setAge(Integer age) {
this.age = age;
}
public void setAddress(Address address) {
this.address = address;
} @Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", age=" + age + ", address=" + address + "]";
}
} - 配置bean
<bean id="address" class="com.qf.demo.Address"></bean>
<!-- set方法属性注入 -->
<bean id="user2" class="com.qf.demo.User">
<property name="id" value="3"/>
<property name="name" value="hz"/>
<property name="age" value="21"/>
<property name="address" ref="address"/>
</bean>
- bean类中定义属性的setter方法
- p名称空间
- 用法
- p名称空间的引入
- xml的beans标签中添加 xmlns:p="http://www.springframework.org/schema/p"
- p名称空间的使用
- 注入普通属性:p:属性名="属性值"
- 注入对象属性:p:属性名-ref="属性值"
- p名称空间的引入
- bean类中定义属性的setter方法(类中必须有属性的setter方法,否则抛出NotWritablePropertyException提示缺少属性的setter方法)
- 配置bean
<?xml version="1.0" encoding="UTF-8"?>
<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"> <bean id="address" class="com.qf.demo.Address"/>
<bean id="user" class="com.qf.demo.User" p:id="4" p:name="wxf" p:age="18" p:address-ref="address"/> </beans>
- 用法
- SpEL注入
- 基本使用
- #{SpEL表达式}
- 字面量表示:#{5}(整数)、#{12.6}(小数)、#{1e3}(科学记数法)、#{'admin'}(字符串)、#{false}(boolean类型)
- 引用bean表示
- 引用其它对象:#{address}(address对象是User类的属性)
- 引用其它对象的属性:#{address.province}(引用address对象的province属性值)
- 引用其它对象的方法:#{address.getProvice()}、#{address?.getProvice()}(如果address是null,就不调用getProvince()方法了)
- #{SpEL表达式}
- bean类中定义定义属性的setter方法
- 配置bean
<bean id="address" class="com.qf.demo.Address" p:province="AnHui" />
<bean id="user" class="com.qf.demo.User">
<property name="id" value="#{5}"/>
<property name="name" value="#{'qf'}"/>
<property name="age" value="#{21}"/>
<property name="address" value="#{address.getInstance()}"/>
</bean>
- 基本使用
注入集合属性
<bean id="collectionBean" class="com.qf.demo.CollectionBean">
<!-- 注入数组 -->
<property name="arr" >
<list>
<value>wxf</value>
<value>admin</value>
<value>qf</value>
</list>
</property> <!-- 注入list -->
<property name="list" >
<list>
<value>asd</value>
<value>zxc</value>
<value>wf</value>
</list>
</property> <!-- 注入set -->
<property name="set" >
<set>
<value>1</value>
<value>2</value>
<value>3</value>
</set>
</property> <!-- 注入数map -->
<property name="map" >
<map>
<entry key="wxf" value="24"></entry>
<entry key="qf" value="18"></entry>
</map>
</property>
</bean>Spring的分模块开发
- 加载配置文件时加载多个
- ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext1.xml","applicationContext2.xml");
- 在配置文件中引入其它配置文件
- <import resource="xxx.xml"/>
注解方式管理Bean
IoC注解的基本使用
- 引入jar,使用spring注解方式管理bean,需要额外再引入aop的jar包:spring-aop-4.2.4.RELEASE.jar
- spring-beans-4.2.4.RELEASE.jar
- spring-context-4.2.4.RELEASE.jar
- spring-core-4.2.4.RELEASE.jar
- spring-expression-4.2.4.RELEASE.jar
- spring-aop-4.2.4.RELEASE.jar
- com.springsource.org.apache.commons.logging-1.1.1.jar
- com.springsource.org.apache.log4j-1.2.15.jar
- 引入配置文件
- 引入context约束
<?xml version="1.0" encoding="UTF-8"?>
<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"> </beans> - 开启组件扫描
<?xml version="1.0" encoding="UTF-8"?>
<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">
<!-- IoC注解开发,配置组件扫描 base-package:哪些包下的类使用注解开发 -->
<context:component-scan base-package="com.qf.demo2"/>
</beans>
- 引入context约束
- 创建spring管理的bean类
- Address.java
package com.qf.demo2; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; @Component("address")
public class Address {
@Value("安徽省")
private String province;
@Value("合肥市")
private String city;
@Override
public String toString() {
return "Address [province=" + province + ", city=" + city + "]";
}
} - User.java
package com.qf.demo2; import javax.annotation.Resource; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; @Component("user")
public class User {
@Value(value="1")
private Long id;
@Value(value="qf")
private String name;
@Value(value="18")
private Integer age;
@Resource(name="address")
private Address address; @Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", age=" + age + ", address=" + address + "]";
}
}
- Address.java
- 测试
- 编写测试类
package com.qf.demo2; import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestDemo {
@Test
public void demo() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User) context.getBean("user");
System.out.println(user);
}
} - 测试结果
User [id=1, name=qf, age=18, address=Address [province=安徽省, city=合肥市]]
- 编写测试类
IoC注解的详细使用
- bean上的注解
- @Component:针对所有Spring管理的bean都可以使用
- @Contoller:针对web层
- @Service:针对service层
- @Repository:针对dao层
- 目前和使用@Component没有区别,但是推荐在web层使用@Contoller、service层使用@Service、dao层使用@Repository,结构更加清晰,而且在新版本的spring可能会扩展新的属性
- 注解设置属性值
- 属性有setter方法,需要将属性注入的注解添加在setter方法上
private String city;
@Value("合肥市")
public void setCity(String city) {
this.city = city;
} - 属性没有setter方法,需要将属性注入的注解添加在属性定义上
@Value(value="qf")
private String name; - 属性上的注解
- 普通属性
- @Value
- 对象属性
- @Autowired:设置对象类型属性的值,按照类型注入
- @Autowired+@Qualifier("名称"):设置对象类型属性的值,按照名称注入
- @Resource(name="名称"):设置对象类型属性的值,相当于@Autowired+@Qualifier("名称")
- @Autowired和@Qualifier是spring框架的注解(org.springframework.beans.factory.annotation.*),@Resource不是spring的注解(javax.annotation.Resource)
- 普通属性
- 属性有setter方法,需要将属性注入的注解添加在setter方法上
- bean生命周期的注解
- @PostConstruct:在bean方法上配置,相当于bean标签的init-method属性(javax.annotation.PostConstruct)
- @PreDestroy:在bean方法上配置,相当于bean标签的destroy-method属性(javax.annotation.PreDestroy)
- bean作用范围的注解
- @Scope("可选值")
- singleton
- prototype
- request
- session
- globalSession
- @Scope("可选值")
XML和注解结合使用
使用XML管理类,使用注解控制属性注入
applicationContext.xml配置文件
- 配置组件扫描
<!-- IoC注解开发,配置组件扫描 base-package:哪些包下的类使用注解开发 -->
<context:component-scan base-package="com.qf.demo2"/>
<bean id="user" class="com.qf.demo2.User"></bean>- 不配置组件扫描
<!--
激活那些已经在spring容器里注册过的bean,
让我们可以在没有配置扫描的情况下,使用属性注入的注解@Resource、@Autowired、@Qulifier、@Value
-->
<context:annotation-config/>
<bean id="user" class="com.qf.demo2.User"></bean>
二、spring的IoC的更多相关文章
- 二 Spring的IOC入门,环境搭建,Spring测试类
IOC:inversion of Control 控制反转,Spring框架的核心.削减计算机程序的耦合问题,把对象(例如JDBC)的创建权交给Spring. IOC的两种类型: 依赖注入: 依赖查 ...
- spring容器IOC创建对象<二>
问题?spring是如何创建对象的?什么时候创建对象?有几种创建方式?测试对象是单例的还是多例的 ?对象的初始化和销毁? 下面的四大模块IOC的内容了!需要深刻理解 SpringIOC定义:把对象的创 ...
- 十二、Spring之IOC容器初始化
Spring之IOC容器初始化 前言 在前面我们分析了最底层的IOC容器BeanFactory,接着简单分析了高级形态的容器ApplicationContext,在ApplicationContext ...
- Spring的IOC和AOP之深剖
今天,既然讲到了Spring 的IOC和AOP,我们就必须要知道 Spring主要是两件事: 1.开发Bean:2.配置Bean.对于Spring框架来说,它要做的,就是根据配置文件来创建bean实例 ...
- Spring框架IOC容器和AOP解析
主要分析点: 一.Spring开源框架的简介 二.Spring下IOC容器和DI(依赖注入Dependency injection) 三.Spring下面向切面编程(AOP)和事务管理配置 一.S ...
- Spring总结—— IOC 和 Bean 的总结
一.Spring 官方文档中给出的 Spring 的整体结构. 二.我自己所理解的 Spring 整体结构图. 三.本次总结 Spring 核心部分 1.从上面图中可以看出,Beans 和 Conte ...
- Spring重点—— IOC 容器中 Bean 的生命周期
一.理解 Bean 的生命周期,对学习 Spring 的整个运行流程有极大的帮助. 二.在 IOC 容器中,Bean 的生命周期由 Spring IOC 容器进行管理. 三.在没有添加后置处理器的情况 ...
- Spring中IOC和AOP的详细解释
我们是在使用Spring框架的过程中,其实就是为了使用IOC,依赖注入,和AOP,面向切面编程,这两个是Spring的灵魂. 主要用到的设计模式有工厂模式和代理模式. IOC就是典型的工厂模式,通过s ...
- Spring的IOC
引用:http://www.cnblogs.com/xdp-gacl/p/4249939.html 学习过Spring框架的人一定都会听过Spring的IoC(控制反转) .DI(依赖注入)这两个概念 ...
- spring的IOC,DI及案例详解
一:spring的基本特征 Spring是一个非常活跃的开源框架:它是一个基于Core来架构多层JavaEE系统的框架,它的主要目的是简化企业开发.Spring以一种非侵入式的方式来管理你的代码,Sp ...
随机推荐
- docker运行redis
查询镜像: zhoumatoMBP:~ zhou$ docker search redis NAME DESCRIPTION STARS OFFICIAL AUTOMATED redis Redis ...
- html5 lineTo的使用例子
demo.js function draw(id) { var CANVAS=document.getElementById(id); var context=CANVAS.getContext('2 ...
- Jquery datatable 配置与应用
var EcommerceOrders = function() { var initPickers = function() { //init date pickers $('.date-picke ...
- 前端每日实战:50# 视频演示如何用纯 CSS 创作一个永动的牛顿摆
效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/qKmGaJ 可交互视频教程 此视频 ...
- python 的set定义
set是集合,跟数学中的集合一样不能重复没有顺序 set定义有两种方式 1. b=set([1, 2, 3, 4]) 2. a={"} 输出: b=set([1, 2, 3, 4])a={1 ...
- Linux复制命令cp进阶
cp -a:连同属性和权限也一起复制 cp -i:如果不带该参数,默认覆盖同名文件而不会提醒. cp -u:只拷贝符合以下条件的文件到目标目录:目标目录中不存在的文件或目标目录中文件版本较旧的文件. ...
- leetcode-15双周赛-1289-下降路径最小和
题目描述: 方法一:动态规划 O(N^3) class Solution: def minFallingPathSum(self, arr: List[List[int]]) -> int: n ...
- uiautomator python版本
摘要: 利用jsonrpc技术直接包装uiautomator,调用uiautomator的api在本地直接编写脚本,然后运行测试case,这样比用Java写,然后再打包,runcase要简单的多,关键 ...
- python-字符、字符串、函数处理
1.列表元祖字典集合 列表 list = ["a", "b", "c", "d"] 元祖 tup = (1, 2, 3, ...
- 生成100个 "20180520" 这样的时间字符串 写入txt文件
主要想记录一下 . 写NSString 到txt . 数组的去重 . 数组的截取 . 数组分割 代码如下: NSString *year = @"2018"; NSArray *m ...