概念
IOC容器是 Spring 框架的核心。容器将创建对象,配置对象,并管理对象的整个生命周期。Spring 容器使用依赖注入(DI)来管理组成一个应用程序的组件。
容器的分类
1,BeanFactory
最简单的容器,给 DI 提供了基本的支持,它用 org.springframework.beans.factory.BeanFactory 接口来定义。BeanFactory 或者相关的接口,如 BeanFactoryAware,InitializingBean,DisposableBean,在 Spring 中仍然存在具有大量的与 Spring 整合的第三方框架的反向兼容性的目的。
2,ApplicationContext
继承了BeanFactory,添加了更多的企业特定的功能,例如从一个属性文件中解析文本信息的能力,发布应用程序事件给感兴趣的事件监听器的能力。该容器是由 org.springframework.context.ApplicationContext 接口定义。通常推荐使用 ApplicationContext。
ApplicationContext 接口的主要实现:
1) FileSystemXmlApplicationContext
基于文件系统中XML文件配置的应用程序上下文
2) ClassPathXmlApplicationContext
基于ClassPath路径中XML文件配置的应用程序上下文
3) AnnotationConfigApplicationConext
基于注解配置的应用程序上下文
Beans节点
bean节点的属性:
id :
对象id,id不能重复
name :
对象名称,name可以重复,如果重复将读取最后一个
class
对象的类型,包名+类名
scope 作用域
singleton**
单例模式,在IOC容器中仅存在一个实例
prototype
多例,每次从IOC容器调用Bean时,都会返回一个新的实例
request
每次Http请求都会创建一个新的Bean,该作用域仅适用于WebApplicationContext环境
session
同一个会话共享一个Bean,不同的会话使用不同的Bean,仅适用于WebApplicationContext环境
application
一般用于portlet应用环境,仅适用于WebApplicationContext环境
属性注入的集中方式
1,set方法注入,就是上面通过property进行配置
2,构造方法注入
给Computer类添加带参数的构造方法,将property改为:
<constructor-arg name="brand" value="苹果"></constructor-arg>
<constructor-arg name="cpu" ref="cpu"></constructor-arg>
<constructor-arg name="memory" ref="memory"></constructor-arg>
3,自动装配
可以通过bean的autowire属性配置
类型:
- **no** 默认,不自动装配
- **byType** 通过类型查找对象,如果相同类型的对象有多个,会出现异常
- **byName** 通过名称查找对象,如果找不到对应的id或name的对象,会出现空指针异常
- **constructor** 通过构造方法装配
Spring的重要注解
- @Component 组件,被标记的类会被Spring扫描到,交给Spring容器进行管理
- @ComponentScan 组件扫描,标记在配置类上,用于扫描某一个包下带@Component的类
- @Configuration 配置类,标记在类上,该类作为配置类代替XML
- @Value 注入值类型数据,配置属性或set方法上
- @Autowrie 自动装配,默认按类型进行注入
- @Qualifier 标记名称,配置在类和注入属性上,用于区分类型相同的对象
- @Resource 自动装配,类似Autowired,默认按名称注入,名称没有再按类型注入
- @Repository 类似@Component,标记DAO实现类
- @Service 类似@Component,标记Service实现类
- @Controller 类似@Component,标记Controller类
IOC实现原理
通过自定义注解+反射机制实现
/**
* 注入值的注解
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyValue {
//注入的值
String value();
}
/**
* 注入对象的注解
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyComponent {
//注入的类型
Class value();
}
/**
* 电脑
*/
public class Computer {
@MyValue("戴尔")
private String brand;
@MyComponent(IntelCpu.class)
private Cpu cpu;
@MyComponent(SumsungMemory.class)
private Memory memory;
/**
* 电脑工厂
*/
public class ComputerFactory {
/**
* 创建电脑对象
* @param computerClass
* @return
*/
public Computer createComputer(Class computerClass) throws Exception {
//反射创建对象
Object computer = computerClass.newInstance();
//遍历所有的属性
Field[] fields = computerClass.getDeclaredFields();
for(Field field : fields){
String fName = field.getName();
//读取自定义注解
MyValue myValue = field.getDeclaredAnnotation(MyValue.class);
if(myValue != null){
//通过反射调用set方法注入值
String mName = "set" + fName.substring(0,1).toUpperCase() + fName.substring(1);
Method set = computerClass.getDeclaredMethod(mName, field.getType());
set.invoke(computer,myValue.value());
}
MyComponent myComponent = field.getDeclaredAnnotation(MyComponent.class);
if(myComponent != null){
//通过反射调用set方法注入对象
String mName = "set" + fName.substring(0,1).toUpperCase() + fName.substring(1);
Method set = computerClass.getDeclaredMethod(mName, field.getType());
//通过配置的类型创建对象
Object obj = myComponent.value().newInstance();
set.invoke(computer,obj);
}
}
return (Computer) computer;
}
}
public class TestFactory {
public static void main(String[] args) {
ComputerFactory factory = new ComputerFactory();
try {
Computer computer = factory.createComputer(Computer.class);
computer.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}