zoukankan      html  css  js  c++  java
  • 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定义资源

  • 相关阅读:
    解决:Could not resolve archetype org.apache.maven.archetypes
    Spring MVC配置MyBatis输出SQL
    Spring集成MyBatis 通用Mapper以及 pagehelper分页插件
    关于SpringMVC或Struts2接受参数接收不到的原因
    配置quartz启动时就执行一次
    ajaxFileUpload进行文件上传时,总是进入error
    spring mvc注入配置文件里的属性
    java中将一个文件夹下所有的文件压缩成一个文件
    flume failed to start agent because dependencies were not found in classpath
    ubuntu不能安装pip unable to install pip in unbuntu
  • 原文地址:https://www.cnblogs.com/Simon-cat/p/10005205.html
Copyright © 2011-2022 走看看