Spring文档阅读之IOC

IOC Inversion Of Controller

IOC
控制反转可以理解为类只定义依赖的对象,容器在创建类的实例时通过依赖对象的构造方法注入依赖的对象(或者在Spring中称为bean).
IOC容器的基础包是org.springframework.beans and org.springframework.context,BeanFactory是Spring Bean容器的入口,ApplicationContext是BeanFactory的子类,是Spring框架提供的引用配置中心接口,在应用运行期间只读,可以配置为热插拔。
简而言之,BeanFactory提供配置框架和基本功能,ApplicationContext提供了应用上下文和更多特异性功能。
ApplicationContext提供:
BeanFactory访问应用组件的方法,继承自ListableBeanFactory。
使用一般方法加载文件资源的能力,继承自ResourceLoader接口。
发布时间到注册的监听器的能力,继承自ApplicationEventPublisher接口。
处理消息和支持国际化的能力,继承自MessageSource接口。
继承自上一级context。定义一个子类context永远会具有优先级。这意味着,一个父类context可以被整个web应用使用,每个servlet都有独立于其他servlet的context。
org.springframework.context.ApplicationContext接口通过读取配置文件(XML,Java注解,Java代码),示例化,配置和组合对象。
IOC使应用的类和配置文件结合,在ApplicationContext创建后,就能使用IOC创建的配置好并且可运行的应用。

IOC配置文件中,通常定义服务层对象,数据访问对象(DAO),显示层对象(Struts Action instance),底层对象(Hibernate SessionFactories, JMS Queues等)。

Bean
IOC容器管理一个或者多个Bean,通过用户配置的xml配置文件(比如application.xml),IOC通过创建对应的BeanDefinition(包含Bean的实际类,Bean的作用范围和生命周期,引用的其他Bean或者Bean使用的连接池的大小)
Bean可以定义一个唯一的id和多个名称(别名),不同的子系统还可以为同一个Bean定义不同的别名并使用。
Bean定义时,需要指定Class参数(即具体的Bean类,IOC实质创建的是一个包含对应类的BeanDefinition实例)。Bean可以使用类定义的构造方法或者通过对应的工厂化类(工厂方法)创建Bean实例。

DI
Dependency Injection 依赖注入
构造方法注入,IOC通过类的构造方法注入依赖。
依赖注入过程:
1.根据用户提供的配置文件,Java配置代码或者注解代码,IOC创建并初始化ApplicationContext。
2.当创建每一个Bean时,根据Bean需要的构造参数,静态构造方法或者配置文件,提供其依赖的其他Bean。

如果Bean的scope不是单实例或者默认,那么它只有在被使用的时候才会被创建而不是随IOC容器一起创建。

循环依赖问题:
如果BeanA和BeanB通过构造方法互相依赖,那么IOC容器初始化BeanA和BeanB的时候,会抛出BeanCurrentlyInCreationException。
一个解决方法是不使用构造方法,而是使用setter方法注入依赖(官方不推荐这种做法)。

自动装配
IOC可以自动装配具有依赖关系的Bean。

当两个类具有不同的生命周期时,可以使依赖类继承并实现ApplicationContextAware接口,这样依赖类可以获取Spring容器的应用上下文ApplicationContext进而获取所需要的Bean实例。

Bean生命周期

Singleton Scope
每个Spring IOC容器只会创建一个对应的Bean,每个引用或者访问对应的Bean实例的请求返回的都是同一个Bean实例(This single instance is stored in a cache of such singleton beans, and all subsequent requests and references for that named bean return the cached object. )。

Prototype Scope
Spring IOC容器会为每一个请求或者引用创建一个Bean的实例,Prototype Scope适用于有状态的Bean,单例生命周期适用于无状态的Bean。

定制Bean特性
Lifecycle Callbacks
可以在Spring IOC管理Bean的不同生命周期时和IOC容器进行互动,比如实现InitializingBean和DisposableBean接口,就可以实现afterPropertiesSet()和destroy()方法在Bean初始化和销毁后进行自定义的操作。Spring官方推荐在方法上添加 @PostConstruct和@PreDestroy注解来代替实现InitializingBean和DisposableBean,对代码的侵入性更小。

ApplicationContextAware
可以获取容器的ApplicationContext,Spring存在一系列的aware接口,就是让aware获取对应的对象,可以看成是一种反馈机制。

基于注解(annotation-based)的IOC配置

@Autowried注解
可以自动注入实现了同一接口的对象,这些对象可以使用@Priority或者@Order对象来定义在集合中的顺序,如
public class MovieRecommender {

@Autowired
private MovieCatalog[] movieCatalogs;

// ...

}
@Primary注解
当存在多个可选择的依赖Bean时,可以使用该定义使当前Bean成为优先被注入的Bean。

@Qualifiers注解
当存在多个可选择的依赖Bean时,可以使用该注解直接定义被注入的Bean的名称(依赖类和被依赖类都要定义同一名称)。

@Resource注解
Spring对于JSR-250 @Resource注解的支持,可以使用该注解定义注入的Bean名称来实现依赖注入。
可以使用@Resource注解来注入当前的ApplicationContext获取应用上下文。

@PostConstruct和@PreDestroy注解
在Bean初始化和Bean销毁前被容器自动调用,可以是用户切入Bean的生命周期。

@Component,@Repository, @Service和@Controller
@Component注解更为通用,@Repository, @Service和@Controller分别适用于持久层和服务表现层,Spring官方推荐使用@Repository, @Service和@Controller使程序更容易理解并且更好的支持AOP功能。

很多Spring的注解都可以使用来生成新的组合功能注解,比如@RestController就是@Controller和@ResponseBody的组合。

一般来说,需要在应用的@Configuration类添加@ComponentScan(basePackages = "org.example")注解使其可以自动扫描并注入实现了被依赖接口的类。

@Bean注解
基本可以认为和@Component注解有一样的效果,和@Configuration一起使用(个人认为不如使用@Component系列注解,更加便于理解并且更好的支持AOP)。
@Configuration
public class AppConfig {

@Bean
public MyService myService() {
    return new MyServiceImpl();
}

}

基于注解的Spring IOC容器创建的是AnnotationConfigApplicationContext,可以通过@Configuration注解的类初始化Spring容器:
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
MyService myService = ctx.getBean(MyService.class);
myService.doStuff();
}

如下代码实现了和@ComponentScan(basePackages = "com.acme") 代码相同的功能,扫描com.acme包并且将所有@Component系列注解注释的类初始化到容器中:
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.scan("com.acme");
ctx.refresh();
MyService myService = ctx.getBean(MyService.class);
}

@Bean注解可以参与容器操作Bean的各个生命周期,最典型的是init和destory:
public class BeanOne {

public void init() {
    // initialization logic
}

}

public class BeanTwo {

public void cleanup() {
    // destruction logic
}

}

@Configuration
public class AppConfig {

@Bean(initMethod = "init")
public BeanOne beanOne() {
    return new BeanOne();
}

@Bean(destroyMethod = "cleanup")
public BeanTwo beanTwo() {
    return new BeanTwo();
}

}
@Configuration注解标识的类表示其是一个Bean定义资源

原文地址:https://www.cnblogs.com/Simon-cat/p/10005205.html