Spring详解篇之IoC控制反转
###一.Spring概况
- spring是一个开源框架
- 是一个轻量的控制反转和面向切面的容器框架
- 大小和开销都是轻量的。
- 通过控制反转技术可以达到松耦合的目的
- 切面编程,允许通过分离应用的业务逻辑。
- 包含并管理应用对象的配置和生命周期,是一个容器,并且能够组装。
二、IoC
ioc控制反转:控制权转移,应用程序本身不负责依赖对象的创建和维护,而是由外部容器负责和维护。ioc的目的是创建对象并且组装对象之间的关系。
####1.bean容器初始化
–org.springframework.beans
–org.springframework.context
beanfactory 提供配置结构和基本功能,加载并初始化bean
applicationContext 保存bean对象并在应用中被应用
2.spring注入:
- spring 注入是指在启动 spring容器加载bean配置的时候,完成对变量的赋值行为。
- 常见的注入方式:设值注入、构建注入
举个例子,构建注入
dao层
public interface InjectionDAO {
public void save(String arg);
}
public class InjectionDAOImpl implements InjectionDAO {
public void save(String arg) {
//模拟数据库保存操作
System.out.println("保存数据:" + arg);
}
}
service 层接口:
public interface InjectionService {
public void save(String arg);
}
service 层实现:
public class InjectionServiceImpl implements InjectionService {
private InjectionDAO injectionDAO;
//构造器注入
public InjectionServiceImpl(InjectionDAO injectionDAO1) {
this.injectionDAO = injectionDAO1;
}
//设值注入
public void setInjectionDAO(InjectionDAO injectionDAO) {
this.injectionDAO = injectionDAO;
}
public void save(String arg) {
//模拟业务操作
System.out.println("Service接收参数:" + arg);
arg = arg + ":" + this.hashCode();
injectionDAO.save(arg);
}
在spring 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="injectionService" class="com.forezp.ioc.injection.service.InjectionServiceImpl">
<constructor-arg name="injectionDAO1" ref="injectionDAO"></constructor-arg>
</bean>
<bean id="injectionDAO" class="com.forezp.ioc.injection.dao.InjectionDAOImpl"></bean>
</beans>
单元测试
本系列文章单元测试基类
public class UnitTestBase {
private ClassPathXmlApplicationContext context;
private String springXmlpath;
public UnitTestBase() {}
public UnitTestBase(String springXmlpath) {
this.springXmlpath = springXmlpath;
}
@Before
public void before() {
if (StringUtils.isEmpty(springXmlpath)) {
springXmlpath = "classpath*:spring-*.xml";
}
try {
context = new ClassPathXmlApplicationContext(springXmlpath.split("[,\\s]+"));
context.start();
} catch (BeansException e) {
e.printStackTrace();
}
}
@After
public void after() {
context.destroy();
}
@SuppressWarnings("unchecked")
protected <T extends Object> T getBean(String beanId) {
try {
return (T)context.getBean(beanId);
} catch (BeansException e) {
e.printStackTrace();
return null;
}
}
protected <T extends Object> T getBean(Class<T> clazz) {
try {
return context.getBean(clazz);
} catch (BeansException e) {
e.printStackTrace();
return null;
}
}
}
单元测试:
@RunWith(BlockJUnit4ClassRunner.class)
public class TestInjection extends UnitTestBase {
public TestInjection() {
super("classpath:spring-injection.xml");
}
@Test
public void testSetter() {
InjectionService service = super.getBean("injectionService");
service.save("这是要保存的数据");
}
@Test
public void testCons() {
InjectionService service = super.getBean("injectionService");
service.save("这是要保存的数据");
}
}
运行打印:
Service接收参数:这是要保存的数据
保存数据:这是要保存的数据:1247298779
这个例子说明,我们可以通过ClassPathXmlApplicationContext.getBean()获取到了service,这个service 是通过xml配置注入到容器中,并且注入的时候通过构造函数的设置了成员变量dao。
三.bean的配置项
####3.1 bean常见的配置项,如下:
- Id
- Class
- Scope
- Constructor arguments
- Properties
- Autowiring mode
- lazy-initialization mode
- Initialization/destruction method
3.2 bean的作用域
- singleton: 单列
- prototype每次使用都会创建新实例
- request :每次http请求创建一个实例,仅在当前 request有效
- session : 当前session有效
举个例子:
测试sinleton和prototype
创建bean实例
public class BeanScope {
public void say() {
System.out.println("BeanScope say : " + this.hashCode());
}
}
在xml中配置,作用域为singleton
<?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="beanScope" class="com.imooc.bean.BeanScope" scope="singleton"></bean>
</beans>
单元测试:
@RunWith(BlockJUnit4ClassRunner.class)
public class TestBeanScope extends UnitTestBase {
public TestBeanScope() {
super("classpath*:spring-beanscope.xml");
}
@Test
public void testSay() {
BeanScope beanScope = super.getBean("beanScope");
beanScope.say();
BeanScope beanScope2 = super.getBean("beanScope");
beanScope2.say();
}
}
运行单元测试:
BeanScope say : 1113008012
BeanScope say : 1113008012
在xml中配置,作用域为prototype
<?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="beanScope" class="com.imooc.bean.BeanScope" scope="prototype"></bean>
</beans>
运行单元测试
BeanScope say : 144724468
BeanScope say : 1432645272
由此可发现sington在bean容器是一个实例,而prototype创建了二个实例。
四.bean的生命周期
包括以下几个方面:
- 定义,在xml中配置
- 初始化
- 使用
- 销毁
初始化
有两种方式
- 实现 InitializingBeean接口,覆盖afterPropertiesSet()
- 配置init-method方法
销毁
也有两种方式:
- 实现DisposableBean接口,覆盖destroy();
- 配置 destroy-method
举个例子:
创建bean实例:
public class BeanLifeCycle implements InitializingBean, DisposableBean {
public void defautInit() {
System.out.println("Bean defautInit.");
}
public void defaultDestroy() {
System.out.println("Bean defaultDestroy.");
}
@Override
public void destroy() throws Exception {
System.out.println("Bean destroy.");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("Bean afterPropertiesSet.");
}
public void start() {
System.out.println("Bean start .");
}
public void stop() {
System.out.println("Bean stop.");
}
}
bean的配置:
<?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"
default-init-method="defautInit" default-destroy-method="defaultDestroy">
<bean id="beanLifeCycle" class="com.imooc.lifecycle.BeanLifeCycle" init-method="start" destroy-method="stop"></bean>
</beans>
单元测试:
@RunWith(BlockJUnit4ClassRunner.class)
public class TestBeanLifecycle extends UnitTestBase {
public TestBeanLifecycle() {
super("classpath:spring-lifecycle.xml");
}
@Test
public void test1() {
super.getBean("beanLifeCycle");
}
}
运行:
Bean afterPropertiesSet.
Bean start .
Bean destroy.
Bean stop.
同时实现两种方式的初始化方法的执行顺序: 接口实现优先于xml中的配置。
五.bean的自动装配(Autowiring)
- No: 不做任何操作
- byname:根据属性名自动装配
- byType:如果容器存在一个与指定类型相同的bean,则自动装配,如果存在多个,则抛出异常。
- constructor:与 byType类似,不同之处它在于构造器的参数。
举例子:
1.byName方式:
创建一个dao:
public class AutoWiringDAO {
public void say(String word) {
System.out.println("AutoWiringDAO : " + word);
}
}
创建一个service
public class AutoWiringService {
private AutoWiringDAO autoWiringDAO;
public void setAutoWiringDAO(AutoWiringDAO autoWiringDAO) {
System.out.println("setAutoWiringDAO");
this.autoWiringDAO = autoWiringDAO;
}
public void say(String word) {
this.autoWiringDAO.say(word);
}
}
在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"
default-autowire="byName">
<bean id="autoWiringService" class="com.imooc.autowiring.AutoWiringService" ></bean>
<bean id="autoWiringDAO" class="com.imooc.autowiring.AutoWiringDAO" ></bean>
</beans>
单元测试:
@RunWith(BlockJUnit4ClassRunner.class)
public class TestAutoWiring extends UnitTestBase {
public TestAutoWiring() {
super("classpath:spring-autowiring.xml");
}
@Test
public void testSay() {
AutoWiringService service = super.getBean("autoWiringService");
service.say(" this is a test");
}
}
运行:
setAutoWiringDAO
AutoWiringDAO : this is a test
通过default-autowire=“byName”;
AutoWiringService 自动获取了autoWiringDAO的实例。
2.byTYpe
将在xml中配置改为byType :
<?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"
default-autowire="byName">
<bean id="autoWiringService" class="com.imooc.autowiring.AutoWiringService" ></bean>
<bean id="autoWiringDAO" class="com.imooc.autowiring.AutoWiringDAO" ></bean>
</beans>
其他不变,运行和byName 一样。
3.constructor
<?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"
default-autowire="constructor">
<bean id="autoWiringService" class="com.imooc.autowiring.AutoWiringService" ></bean>
<bean id="autoWiringDAO" class="com.imooc.autowiring.AutoWiringDAO" ></bean>
</beans>
AutoWiringService 中增加构造器
public class AutoWiringService {
private AutoWiringDAO autoWiringDAO;
public AutoWiringService(AutoWiringDAO autoWiringDAO) {
System.out.println("AutoWiringService");
this.autoWiringDAO = autoWiringDAO;
}
public void setAutoWiringDAO(AutoWiringDAO autoWiringDAO) {
System.out.println("setAutoWiringDAO");
this.autoWiringDAO = autoWiringDAO;
}
public void say(String word) {
this.autoWiringDAO.say(word);
}
}
允行:
AutoWiringDAO : this is a test
六.classPath扫描与组件管理
从spring 3.0开始,spring javaConfig 项目提供了许多特性,包括使用java而不是xml
1.比如注解
@Configuration
@Bean
@Import
@DependsOn@Component 是一个通用注解,应用于任何bean
@Reposity注解DAO
@Service注解service
@Controller注解controller
2.spring可以自动检测类并注册bean到applicationContext中。比如
@Service @Reposity等
3.< context:annoation-config />会查找applicationContext中bean的注解。
扫描 :< context:component-scan> 包含< context:annoation-config/>,通常只需要使用前者。
<context:component-scan base-package="com.forezp" >
举个例子:
通过扫描获取bean,在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"
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.forezp.beanannotation"></context:component-scan>
</beans>
定义一个bean类:
其中scope 注解表示bean的作用域,默认singleton。Component默认类名并将第一个字母小写。
@Scope
@Component
public class BeanAnnotation {
public void say(String arg) {
System.out.println("BeanAnnotation : " + arg);
}
public void myHashCode() {
System.out.println("BeanAnnotation : " + this.hashCode());
}
}
单元测试:
@RunWith(BlockJUnit4ClassRunner.class)
public class TestBeanAnnotation extends UnitTestBase {
public TestBeanAnnotation() {
super("classpath*:spring-beanannotation.xml");
}
@Test
public void testSay() {
BeanAnnotation bean = super.getBean("beanAnnotation");
bean.say("This is test.");
//bean = super.getBean("bean");
//bean.say("This is test.");
}
}
运行:
BeanAnnotation : This is test.
七、Autowired
- @Autowired可以用于setter方法上
- 可以用于成员变量
- 可以用于构造器
举个例子:
采用包扫描:
<?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" >
<context:component-scan base-package="com.forezp.beanannotation"></context:component-scan>
</beans>
采用注解:DAO层
@Repository
public class InjectionDAOImpl implements InjectionDAO {
public void save(String arg) {
//模拟数据库保存操作
System.out.println("保存数据:" + arg);
}
}
service层:
@Service
public class InjectionServiceImpl implements InjectionService {
// @Autowired
private InjectionDAO injectionDAO;
@Autowired
public InjectionServiceImpl(InjectionDAO injectionDAO) {
this.injectionDAO = injectionDAO;
}
// @Autowired
public void setInjectionDAO(InjectionDAO injectionDAO) {
this.injectionDAO = injectionDAO;
}
public void save(String arg) {
//模拟业务操作
System.out.println("Service接收参数:" + arg);
arg = arg + ":" + this.hashCode();
injectionDAO.save(arg);
}
}
单元测试:
@RunWith(BlockJUnit4ClassRunner.class)
public class TestInjection extends UnitTestBase {
public TestInjection() {
super("classpath:spring-beanannotation.xml");
}
@Test
public void testAutowired() {
InjectionService service = super.getBean("injectionServiceImpl");
service.save("This is autowired.");
}
}
运行:
Service接收参数:This is autowired.
保存数据:This is autowired.:1641742937
八、基于java的容器注解@Bean
- @Bean 标识一个用于配置和初始化一个由springIoC容器管理的新对象的方法,类似于 xml配置文件的</ bean>
举个例子:
用注解去代替xml文件
@Configuration
public class StoreConfig {
@Bean(name = "stringStore", initMethod="init", destroyMethod="destroy")
public Store stringStore() {
return new StringStore();
}
javabean StringStore类
public class StringStore implements Store<String> {
public void init() {
System.out.println("This is init.");
}
public void destroy() {
System.out.println("This is destroy.");
}
}
单元测试:
@RunWith(BlockJUnit4ClassRunner.class)
public class TestJavabased extends UnitTestBase {
public TestJavabased() {
super("classpath*:spring-beanannotation.xml");
}
@Test
public void test() {
Store store = super.getBean("stringStore");
System.out.println(store.getClass().getName());
}
}
另外可以用ImportResource注解类获取资源文件信息:
@Configuration
@ImportResource("classpath:config.xml")
public class StoreConfig {
@Value("${url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${password}")
private String password;
九、JSR-250
- spring支持jsr-250
- @Resource注解变量或者setter 方法
- Resource注解有一个name属性,默认该值作为被注入bean的名称。
举个例子:
Dao层:
@Repository
public class JsrDAO {
public void save() {
System.out.println("JsrDAO invoked.");
}
}
service层:
@Service
public class JsrServie {
@Resource
private JsrDAO jsrDAO;
// @Resource
// public void setJsrDAO(@Named("jsrDAO") JsrDAO jsrDAO) {
// this.jsrDAO = jsrDAO;
//}
@PostConstruct
public void init() {
System.out.println("JsrServie init.");
}
@PreDestroy
public void destroy() {
System.out.println("JsrServie destroy.");
}
public void save() {
jsrDAO.save();
}
}
扫码关注公众号有惊喜
(转载本站文章请注明作者和出处 方志朋的博客)
Spring详解篇之IoC控制反转的更多相关文章
- Spring Boot笔记十:IOC控制反转
目录 IOC控制反转和DI依赖注入 IOC实现Hello World Spring IOC容器怎么知道哪些是管理的对象? IOC容器getBean方法的三种签名 xml配置文件的import导入 @A ...
- 【转】跟我一起学Spring 3(4)–深入理解IoC(控制反转)和DI(依赖注入)
在继续下面的章节之前,我们要先说说大名鼎鼎的IoC和DI. 我们经常会听说IoC,也就是Inversion of Controller,控制反转.事实上,IoC并不是一个新鲜的概念,最早可能是在198 ...
- Spring.Net-DI依赖注入和Ioc控制反转
Spring.Core作为整个Spring框架的基础,实现了依赖注入的功能.Spring框架的其它模块都要依赖或扩展该模块. IObjectFactory接口,该接口实现了工厂模式,使用它可以帮我们创 ...
- 【spring学习笔记一】Ioc控制反转
(最近有点捞,在大一的时候还通过写博客的方式督促自己学习唉,先培养起习惯,再找个好点的地方重新开始写博客⑧) Spring是JAVA的一个框架. 有个概念叫依赖注入(或者还有个名字叫控制反转). 概念 ...
- Spring详解篇之 AOP面向切面编程
一.概述 Aop(aspect oriented programming面向切面编程),是spring框架的另一个特征.AOP包括切面.连接点.通知(advice).切入点(pointCut) . 1 ...
- Spring框架之IOC(控制反转)
[TOC] 第一章Spring框架简介 IOC(控制反转)和AOP(面向方面编程)作为Spring框架的两个核心,很好地实现了解耦合.所以,简单来说,Spring是一个轻量级的控制反转(IoC)和面向 ...
- Spring详解(二)------IOC控制反转
我相信提到 Spring,很多人会脱口而出IOC(控制反转).DI(依赖注入).AOP等等概念,这些概念也是面试官经常问到的知识点.那么这篇博客我们就来详细的讲解 IOC控制反转. ps:本篇博客源码 ...
- Spring IOC(控制反转)详解及示例
控制反转——Spring通过一种称作控制反转(IOC)的技术促进了低耦合.当应用了IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象.你可以认为IoC与JN ...
- Spring的三大核心思想:IOC(控制反转),DI(依赖注入),AOP(面向切面编程)
Spring核心思想,IoC与DI详解(如果还不明白,放弃java吧) 1.IoC是什么? IoC(Inversion of Control)控制反转,IoC是一种新的Java编程模式,目前很多 ...
随机推荐
- inventor安装失败怎样卸载安装inventor 2014?
AUTODESK系列软件着实令人头疼,安装失败之后不能完全卸载!!!(比如maya,cad,3dsmax等).有时手动删除注册表重装之后还是会出现各种问题,每个版本的C++Runtime和.NET f ...
- SourceTree 关于 .gitignore使用/下载
# =============== # # Unity generated # # =============== # Temp/ Obj/ UnityGenerated/ Library/ Asse ...
- Host 'XXX' is not allowed to connect to this MySQL server解决方案
如何允许远程连接mysql数据库呢,操作如下: 首先登录账号 mysql -uroot -p 使用mysql用户 use mysql 如果报此类错:ERROR 1820 (HY000): You mu ...
- If you are tired...
如果你累了 1. 深呼吸 放松身体,深呼吸五分钟. 2. 听音乐 静静地听几首歌放松一下就好了,比如王豪学长推荐的追梦赤子心,骄傲的少年. 3. 冥想 放松身体,处于冥想状态. 4. 干洗脸.鸣天鼓. ...
- Docker学习笔记(2)-docker镜像操作
本节将会涉及Docker的镜像操作. 1. 获取镜像 如何获取Docker Hub上的镜像?可通过docker pull命令获取,其格式为: docker pull [选项] [Docker Regi ...
- Fsharp 类中的空字段
fsharp设计之初就尽可能的避免使用null.在我的编程经验中null真是个错误之源,垃圾代码之源,95%的系统奔溃之源.其实在设计之初就应该考虑你的系统需要null表现什么?是未初始化的状态,还是 ...
- Ajax Jq Razor语句
1.JS刷新当前页面: window.location.reload(); 2.JSon成功后转向其他页面: window.location.href="要转向页面的地址(一般格式:/页面所 ...
- carousel 插件隐藏列表中几项导致左右切换出错
1. 一般的应用场景: 用于左右快速切换显示的列表内容,比如对员工的切换. 对于这种情况必不可少需要按照部门进行搜索,目前我的做法是首次加载所有该用户可以查看的员工列表,选择部门后又选择的隐藏掉其他不 ...
- MyEclipse内存溢出问题
今天碰到的问题,先记录下来 Console报错: Java.lang.OutOfMemoryError: PermGen space 跟着步骤: 在这里加入:-Xms800m -Xmx800m -XX ...
- Linux系统错误码对照表
C Name Value Description EPERM 1 Operation not permitted ENOENT 2 No such file or directory ESRCH 3 ...