Skip to content

IoC容器

Inversion of Control.

Spring的核心就是提供了一个IoC容器,它可以管理所有轻量级的JavaBean组件,提供的底层服务包括组件的生命周期管理、配置和组装服务、AOP支持,以及建立在AOP基础上的声明式事务服务等。 - 将组件的创建+配置与组件的使用相分离 - 共享组件

基础

  • BeanFactory: a basic IoC container interface which a parent interface of ApplicationContext.
@SpringBootApplication
// Main class
public class DemoApplication 
{
// Main driver method
  public static void main(String[] args) 
  {
    // Creating object in a spring container (Beans)
    BeanFactory factory = new ClassPathXmlApplicationContext("bean-factory-demo.xml");
    Student student = (Student) factory.getBean("student"); // 或者是 context.getBean("name", Class<T> requiredType)

    System.out.println(student);
  }
}
  • ApplicationContext: is the sub-interface of BeanFactory. 它 provides 一些 enterprise-specific functionalities, 所以开发者一般使用这个。
    • 在加载上,BeanFactory在初始化容器的时候,并未实例化Bean,直到需要使用某个Bean(调用getBean()方法) 时才实例目标Bean,导致不能及时发现可能存在的一些配置上的问题。ApplicationContext 则在初始化应用上下文时就实例化所有单实例的Bean,有助于发现配置问题及提高运行时速度;但它占用内存空间,配置的Bean较多时,启动会比较慢。

装配 Bean

ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");

Spring容器就是ApplicationContext,它是一个接口,有很多实现类,如ClassPathXmlApplicationContext,表示它会自动从classpath中查找指定的XML配置文件。

获得了ApplicationContext的实例,就获得了IoC容器的引用。从ApplicationContext中可以根据Bean的ID或者Bean的类型获取Bean的引用。

可以注入给 interface 或者 enum 吗?

不行,因为它们是 final. First of all, public static non-final fields are evil. Spring does not allow injecting to such fields for a reason.

Annotation

简化 xml 的配置

@Configuration
@ComponentScan
public class AppConfig {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        UserService userService = context.getBean(UserService.class);
        User user = userService.login("bob@example.com", "password");
        System.out.println(user.getName());
    }
}

定制 Bean

scope

  • 默认:单例
  • 原型:我们每次调用getBean(Class),容器都返回一个新的实例,这种Bean称为Prototype(原型),它的生命周期显然和Singleton不同。声明一个Prototype的Bean时,需要添加一个额外的@Scope注解

可选注入

@Autowird(required = false)

第三方Bean

@Configuration
@ComponentScan
public class AppConfig {
    // 创建一个Bean:
    @Bean
    ZoneId createZoneId() {
        return ZoneId.of("Z");
    }
}

初始化和销毁

在Bean的初始化和清理方法上标记@PostConstruct@PreDestroy

别名

可以用@Bean("name")指定别名,也可以用@Bean+@Qualifier("name")指定别名。

Resource与注入配置

  • resource: @Value("classpath:/logo.txt")
  • 注入配置:容器加注解 @PropertySource("app.properties")

条件装配

在运行程序时,加上JVM参数-Dspring.profiles.active=test就可以指定以test环境启动。 - 在 Bean 上注解:@Profile("test")

实践

获取 ApplicationContext 实例

实现 ApplicationContextAware 接口

public class SpringContextHolder implements ApplicationContextAware {
     @Override
    public void setApplicationContext(ApplicationContext appContext) {
        applicationContext = appContext;
    }
}