英文名:Inversion of control
定义:把对象的创建、初始化、销毁工作交给spring容器来做,由spring容器来管理对象的生命周期
1、IOC不是一种技术,只是一种开发思想,一种重要的面向对象编程的法则。可以设计出松耦合更加优良的系统程序。
2、IOC包括两部分:依赖注入(DI)和依赖查找。
3、spring 的注入:就是在实例化这个类的时候,由外部的容器来设置这个对象的值。
IOC包括依赖注入(DI)和依赖查找(依赖注入是核心)
我们可以实现只是定义,不需要进行getBean获取了
我们还是使用上一次建的项目。
现在新建一个User类
package com.cbb.bean;
import java.util.List;
import java.util.Map;
/**
* 类描述:注入各种类型的
* 作者: 地铁与人海
* 创建日期:2019年3月12日
* 修改人:
* 修改日期:
* 修改内容:
* 版本号: 1.0.0
*/
public class User {
private int id;
private String name;
private List scores;
private Map info;
private Car car;//汽车 注入类
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List getScores() {
return scores;
}
public void setScores(List scores) {
this.scores = scores;
}
public Map getInfo() {
return info;
}
public void setInfo(Map info) {
this.info = info;
}
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", scores=" + scores + ", info=" + info + ", car=" + car + "]";
}
}
其中的Car的定义我们先不使用,你可以先注释掉,然后改一下我们生成的方法。
ps:一定要有setter方法,有setter方法才能注入
我们继续在applicationContext.xml中进行配置Bean
我们再测试使用一下,还是在BeanTest.java中
@Test
public void IOCtest() {
//加载spring容器
ApplicationContext app =
new ClassPathXmlApplicationContext("applicationContext.xml");
//获取springbean
User user = app.getBean("user", User.class);
System.err.println(user.toString());//属性为空,这个对象不是空
}
结果我们可以获取到对象(和上一篇的例子一样),但里面的属性为空。
所以我们现在要干的事情,就是在获取对象的时候,由外部容器来设置这个对象的值。
属性的注入要由容器来完成,所以就要在容器中再次进行配置可以配置的选项如图:
property是我们常用的属性注入标签
支持的类型有:
注意:一定要有set方法才能注入
下面是使用
100
76
然后我们再运行方法,就发现可以出来我们设计的数据了。
我这还有更全的数据类型注入:
这是属性
public class Person {
private String name;
private Integer age;
private String[] strs;
private List coll;
private Set sets;
private Map mm;
}
这是配置
CCCCC
DDDDD
aa
bb
AAAA
BBBB
你们可以对应来看。
现在我们来进行注入其他类的实现。
首先,我们要注入的其他类也需要在spring容器内管理,也就是需要在applicationContext.xml里面配置
明白了只一点我们进行配置。
先写一个小汽车类
package com.cbb.bean;
/**
* 类描述:汽车类
* 作者: 地铁与人海
* 创建日期:2019年3月12日
* 修改人:
* 修改日期:
* 修改内容:
* 版本号: 1.0.0
*/
public class Car {
private String carName;
public String getCarName() {
return carName;
}
public void setCarName(String carName) {
this.carName = carName;
}
@Override
public String toString() {
return "Car [carName=" + carName + "]";
}
}
配置
我们进行在user中进行car的注入
100
76
要写在上面的pplicationContext.xml`里面。
然后我们再运行一下方法,就能实现了。
1、singleton:单例模式(缺省默认)(默认情况下)spring容器中只存在一个实例
2、prototype:原型模式。每次通过spring容器获取bean时,容器会创建一个新的实例进行返回
3、request:在同一次请求中,获取的是同一个实例,不同的请求获取的是不同的实例。
4、session:在同一次会话中,获取的是同一个实例,不同的会话求获取的是不同的实例。
Spring 容器可以管理 singleton 作用域下 Bean 的生命周期,在此作用域下,Spring能够精确地知道 Bean 何时被创建,何时初始化完成,以及何时被销毁。而对于 prototyp作用域的 Bean,Spring 只负责创建,当容器创建了 Bean 的实例后,Bean 的实例就交给了客户端的代码管理,Spring 容器将不再跟踪其生命周期,并且不会管理那些被配置成prototype 作用域的 Bean 的生命周期
1、构造器实例化
Spring 容器通过 Bean 对应的默认的构造函数来实例化 Bean。
2、静态工程方式实例化
通过创建静态工厂的方法来创建 Bean 的实例
我们要写一个mvc设计模式的项目,就需要在service层中new一个dao实现对象,在controller层中new一个service实现对象,在Test层中new一个controller层对象。
现在我们使用spring来统一管理,就只需要对对象进行定义即可。
然而我们还需要加上,是我们new的这个对象的getter和setter方法(setter方法更重要),所以就形成了下面的例子。
这是我们的目录结构,(不需要pojo类,就没写)
下面是各个类
package com.cbb.controller;
import com.cbb.service.UserService;
public class UserController {
/*private UserService userService = new UserServiceImpl();*/
private UserService userService;
public void login() {
System.err.println("controller......login......");
userService.login();
}
public UserService getUserService() {
return userService;
}
public void setUserService(UserService userService) {
this.userService = userService;
}
}
package com.cbb.dao;
public interface UserDao {
/**
* 方法描述:
*/
void login();
}
package com.cbb.dao.impl;
import com.cbb.dao.UserDao;
public class UserDaoImpl implements UserDao {
@Override
public void login() {
System.err.println("Dao......login......");
}
}
package com.cbb.service;
public interface UserService {
/**
* 方法描述:
*/
void login();
}
package com.cbb.service.impl;
import com.cbb.dao.UserDao;
import com.cbb.service.UserService;
public class UserServiceImpl implements UserService {
/* private UserDao userDao = new UserDaoImpl();*/
private UserDao userDao;
@Override
public void login() {
System.err.println("service......login......");
userDao.login();
}
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
package com.cbb.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.cbb.controller.UserController;
import com.cbb.dao.impl.UserDaoImpl;
public class SpringTest {
@Test
public void Test() {
System.err.println("正常的方法");
}
@Test
public void test2() {
ApplicationContext app =
new ClassPathXmlApplicationContext("applicationContext.xml");
UserController uc = app.getBean("userController", UserController.class);
uc.login();
//测试一下直接获取dao层的方法
UserDaoImpl ud = app.getBean("ud", UserDaoImpl.class);
ud.login();
}
}
上面有两处使用的是构造器实例化 ,也有两处使用的是静态工程方式实例化(其中一个是测试),你们可以找一下。
好吧,test类中使用的是金改工程方式实例化的。
使用这种方法需要注意:
1、属性注入需要有 对应的setter方法
2、注入其他类 bean要有无参构造方法
这是第二种配置方式
首先我们需要导入一个新的jar包
你们可以对比发现,多了一个aop包。
然后我们写一个配置文件
直接一句话搞定
但注意他的功能是只有被注解的才会被扫描。
然后我们对各个类进行注解,使用的标签和作用如下
默认bean的名字,是类名首字母小写,也可以自己定义
四个组件。
然后我们还需要在定义对象的时候进行注解。
也就是用@Autowired(还有其他的)
然后我们就可以删掉类里面的get和set方法了。
上面的注解也会有错误,因为UserService有可能有两个实现类。
@Qualifierd//指定bean的名字
@Resource //会根据属性的名字去查找对应的bean,如果查找不到,再根据类型进行匹配
然后就可以正常使用了。
ps:依赖查找是什么,我不太清楚,希望有大神可以帮帮我
END