1.IOC是什么?
ioc(inverse of controll ) 控制反转。
所谓控制反转就是把**创建对象(bean)和维护对象(bean)**的关系的权利从程序中转移到spring的容器(applicationContext.xml),而程序本身不再维护。
DI是什么?
di(dependency injection) 依赖注入: 实际上di和ioc是同一个概念,spring设计者认为di更准确表示spring核心技术
2.IOC如何获取bean
从ApplicationContex 应用上下文容器中获取bean和从bean工厂容器中获取bean
1 2 3 4 5 6 7 8 9 10 11 12
| //从ApplicationContext中取bean ApplicationContext ac=new ClassPathXmlApplicationContext("com/hsp/ioc/beans.xml"); //当我们去实例化beans.xml,该文件中配置的bean被实例(该bean scope是 singleton)从bean中取出student //如果我们使用beanfactory去获取bean,当你只是实例化该容器, 那么 //容器的bean不被实例化,只有当你去使用getBean某个bean时,才会实时的创建. BeanFactory factory = new XmlBeanFactory( new ClassPathResource("com/hsp/ioc/beans.xml")); factory.getBean("student");
|
两者的区别:
1.如果使用ApplicationContext ,则配置的bean如果是 singlton不管你用不用,都被实例化.(好处就是可以预先加载,缺点就是耗内存)
2.如果是 BeanFactory ,则当你获取beanfacotry时候,配置的bean不会被马上实例化,当你使用的时候,才被实例(好处节约内存,缺点就是速度)
3.IOC处理对象的依赖关系
set注入的缺点是无法清晰表达哪些属性是必须的,哪些是可选的,构造注入的优势是通过构造强制依赖关系,不可能实例化不完全的或无法使用的bean。
3.1 set方法注入值
- 普通字段赋值
- 集合属性 (list/map/property)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| public class Department {
private String name; private String [] empName; private List<Employee> empList; private Set<Employee> empsets; private Map<String,Employee> empMaps; public Set<Employee> getEmpsets() { return empsets; } public void setEmpsets(Set<Employee> empsets) { this.empsets = empsets; } public String[] getEmpName() { return empName; } public void setEmpName(String[] empName) { this.empName = empName; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<Employee> getEmpList() { return empList; } public void setEmpList(List<Employee> empList) { this.empList = empList; } public Map<String, Employee> getEmpMaps() { return empMaps; } public void setEmpMaps(Map<String, Employee> empMaps) { this.empMaps = empMaps; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| package com.hsp.collection; public class Employee { private String name; private int id; 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; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| <bean id="department" class="com.hsp.collection.Department"> <property name="name" value="财务部"/> <property name="empName"> <list> <value>小明</value> <value>小明小明</value> <value>小明小明小明小明</value> </list> </property> <property name="empList"> <list> <ref bean="emp2" /> <ref bean="emp1"/> <ref bean="emp1"/> </list> </property> <property name="empsets"> <set> <ref bean="emp1" /> <ref bean="emp2"/> <ref bean="emp2"/> </set> </property> <property name="empMaps"> <map> <entry key="11" value-ref="emp1" /> <entry key="22" value-ref="emp2"/> <entry key="33" value-ref="emp1"/> </map> </property> 【点http协议 referer 】 <property name="pp"> <props> <prop key="pp1">abcd</prop> <prop key="pp2">hello</prop> </props> </property> </bean> <bean id="emp1" class="com.hsp.collection.Employee"> <property name="name" value="北京"/> <property name="id" value="1"/> </bean> <bean id="emp2" class="com.hsp.collection.Employee"> <property name="name" value="天津"/> <property name="id" value="2"/> </bean>
|
1 2 3 4 5 6 7
| <bean id=”foo” class=”....Foo”> <property name=”属性”> <!—第一方法引用--> <ref bean=’bean对象名’/> </property> </bean>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public class Student { private String name; private String age; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAge() { return name; } public void setAge(String age) { this.name = name; } } public class Gradate extends Student{ .... }
|
1 2 3 4 5 6 7 8 9 10 11 12
| 在beans.xml文件中体现配置
<bean id="student" class="com.hsp.inherit.Student"> <property name="name" value="顺平" /> <property name="age" value="30"/> </bean>
<bean id="grdate" parent="student" class="com.hsp.inherit.Gradate"> <property name="name" value="小明"/> <property name="degree" value="学士"/> </bean>
|
3.2 构造函数赋值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public class Employee {
private String name; public Employee(){ } public Employee(String name, int age) { System.out.println("Employee(String name, int age) 函数被调用.."); this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; }
}
|
index:第几个参数
type:参数类型
value:参数
spring会根据传入的参数,自动调用相应的狗崽函数
1 2 3 4 5
| <bean id="employee" class="com.hsp.constructor.Employee"> <constructor-arg index="0" type="java.lang.String" value="大明" /> </bean>
|
3.3自动装配bean的属性值(autowire=”….”)
Spring官方文档说明

原理

(1) byName: byName:寻找和属性名相同的bean,找不到,装不上
(如下面的例子:当master和dog对象加载到内存中时,master中的dog其实是个null。当在获取bean的时候master.getDog().getName (),ioc会根据你设置autowire=“byName” ,来从内存中查找对象名=dog的,然后把dog对象的内存地址给master的dog属性)
(2) byType: byType:寻找和属性类型相同的bean,找不到,装不上,找到多个抛异常。
(同byName原理一样,只是要查找类型是dog类型的对象,名字可以不相同,但是类型相同就行)
(3) constructor: autowire=”constructor”
说明 : 查找和bean的构造参数一致的一个或多个bean,若找不到或找到多个抛异常。按照参数的类型装配
(查找master中有没有狗杂函数,用于接受dog对象)
1 2 3
| public Master(Dog dog){ this.dog = dog; }
|
(4) autodetect
说明 : autowire=”autodetect”(3)和(2)之间选一个方式。不确定性的处理与(3)和(2)一致。
(5) defualt
autowire默认是defualt,而defualt-autorwire默认是no
这个需要在
当你在指定了 default-atuowrite后, 所有的bean的 默认的autowire就是 指定的装配方法;
如果没有在 没有 defualt-autorwire=“指定” ,则默认是
defualt-autorwire=”no”
调用xml配置文件
1 2 3 4 5 6 7 8 9 10 11
| public static void main(String[] args) { ApplicationContext ac=new ClassPathXmlApplicationContext("com/hsp/autowire/beans.xml"); Master master=(Master) ac.getBean("master"); System.out.println(master.getName()+" 养 "+master.getDog().getName()); }
}
|
Master和Dog对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| public class Master {
private String name; private Dog dog; public String getName() { return name; } public void setName(String name) { this.name = name; } public Dog getDog() { return dog; } public void setDog(Dog dog) { this.dog = dog; } }
public class Dog { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
|
xml配置文件
1 2 3 4 5 6 7 8 9 10
| <bean id="master" class="com.hsp.autowire.Master" autowire="byName"> <property name="name"> <value>顺平</value> </property> </bean>
<bean id="dog111" class="com.hsp.autowire.Dog"> <property name="name" value="小黄"/> <property name="age" value="3"/> </bean>
|
3.4 通过注解配置ioc
配置方式与注解方式区别:
1. 配置, 便于维护(配置过多,比较繁琐)
2. 注解, 开发方便(简化配置,不利于后期维护,如果修改对象创建、关系处理,需要改代码!)
3.4.1 将bean注入到ioc中
@Component
表示一个组件(类),把当前组件加入ioc容器加入容器的组件的名称默认是类名第一个字母小写,
@Component("classname")
指定加入ioc容器的组件类的类名
相当于如下所示
1
| <bean id="classname" class="..."><bean/>
|
以下注解作用和@Component
一样,只是更容易区分组件类型
@Repository
标识是一个持久层的组件
@Service
标识是一个业务逻辑层的组件
@Controller
标识是一个控制层的组件
3.4.1 处理bean中的依赖关系
@Resource
- 默认根据修饰的字段名称会取ioc容器找对象自动注入找到后注入
- 如果名称没有找到,再根据类型查找 找到后就立刻注入。如果改类型在ioc容器中有多个对象,报错!
- 根据类型也没有找到对象,报错!
@Resource(name ="")
会根据指定的名称去容器找对象自动注入
相当于如下所示1 2 3
| <bean id="classname" class="..."> <property name="" ref="beanid"/> <bean/>
|
代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
@Service public class UserService implements IUserService { @Resource private IUserDao userDao;
public void save() { userDao.save(); } }
|