Spring Boot之注解下的IOC

之前写了Springboot的一些入门,至于怎么搭建SpringBoot项目,网上一大堆,就不再阐述了。
ICO:控制反转,依赖注入,对于IOC的概念,大家已经滚瓜烂熟了,这里不再多加阐述(Spring最成功的就是IOC和AOP这两个核心理念,所以思想值得学习,原理搞清楚会对自己帮助很大)
IOC比较简单,这里简单总结一些重要的知识点

  • IOC的定义:ioc是一种通过描述生成或者获取对象的技术

  • IOC的两个基本功能:

    • 通过描述管理Bean,包括发布和获取Bean
    • 通过描述完成Bean之间的依赖关系
  • IOC容器都需要实现的顶级容器接口:BeanFactory

    Package org.springframework.beans.factory;
    import org.springframework.beans.BeansException;
    improt org.springframework.core.ResolvableType;
    public interface BeanFactory{
        // 前缀
        String FACTORY_BEAN_PREFIX="&";  
    /**
        返回指定BeanName(或别名)的Bean
        对Protorype:每次返回不同的实例
        对Singleton:每次返回相同的实例
    */
        Object getBean(String name) throws BeansException;
        
    /**
        返回同时匹配指定BeanName(或别名)和类型的Bean
        对Protorype:每次返回不同的实例
        对Singleton:每次返回相同的实例
    */
        <T> T getBean(String name, Class<T> requiredType) throws BeansException;
        /**
        返回指定BeanName(或别名)的Bean,并把所提供的参数作为构造函数参数或工厂方法参数初始化Bean
        对Protorype:每次返回不同的实例
        对Singleton:抛出BeanDefinitionStoreException异常
    */
        Object getBean(String name, Object... args) throws BeansException;
    /**
        返回指定类型的Bean,如果存在多个bean定义有相同的类型,则抛NoUniqueBeanDefinitionException异常
        对Protorype:每次返回不同的实例
        对Singleton:每次返回相同的实例
    */
        <T> T getBean(Class<T> requiredType) throws BeansException;
        
        /**
        返回指定类型的Bean,并把所提供的参数作为构造函数参数或工厂方法参数初始化Bean
        对Protorype:每次返回不同的实例
        对Singleton:抛出BeanDefinitionStoreException异常
    */
        <T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
        /**
        返回一个ObjectProvider<T>该类型允许对Bean处于not available情况和not-unique情况时做处理
    */
        <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);
    /**
        作用同上
    */
        <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);
        /**
        根据指定的BeanName或别名判断factory是否包含bean定义(concrete
         or abstract, lazy or eager, in scope or not)或由外部注册的单例,
        返回true时并不保证一定能通过getBean获取相应实例(eg: 抽象Bean)
    */
        boolean containsBean(String name);
    
    /**
        根据指定的BeanName或别名判断factory中该Bean的scope是否是Singleton
        返回false时不代表scope是prototype(使用自定义的scope时)
    */
        boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
    /**
        根据指定的BeanName或别名判断factory中该Bean的scope是否是Prototype
        返回false时不代表scope是Singleton(使用自定义的scope时)
    */
        boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
    
    /**
        根据指定的BeanName或别名判断factory中该Bean的类型是否与提供的类型匹配
    */
        boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
    
    /**
        根据指定的BeanName或别名判断factory中该Bean的类型是否与提供的类型匹配
    */
        boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
    /**
        根据指定的BeanName或别名获取factory中该Bean的类型,对于FactoryBean类型,将调用它的
        getObjectType()
    */
        @Nullable
        Class<?> getType(String name) throws NoSuchBeanDefinitionException;
    
    /**
        根据指定的BeanName或别名返回factory中该Bean的别名,
        如果提供的时别名将返回BeanName和其他别名的数组,BeanName
        置与第一个元素
    */
        String[] getAliases(String name);
        
    }
    
    • isSingleton==true:单例模式 ,每次返回的都是同一个对象
    • isPrototype==true:每次使用getBean获取对象时,IOC容器就会创建一个新的Bean返回给调用者。
  • 注解:

    • @Bean:将bean注入到IOC容器中

    • @Component:哪个类被扫描进入Spring IOC容器

    • @ComponentScan:表明采用何种策略去扫描装配Bean,默认只会扫描当前包和其子包,但是也允许我们自定义扫描包

      • 配置项

        • basePackages:定义扫描的包名

        • basePackageClasses:定义扫描的类

        • includeFilters:定义满足过滤器条件的Bean才去扫描

        • excludeFilters:排除过滤器条件的Bean

          注意:他们都需要通过一个注解@Filter去定义,他有一个type类型,这里可以定义为注解或者正则表达式等类型。classes定义注解类,pattern定义正则表达式。

          eg:不想扫描包下面的service类

          @ComponentScan(basePackages="com.springboot.*",
          excludeFilters={@Filter(classes={service.class})})
          
          • 所有标注了@Service的类将不被IOC容器扫描注入
    • main方法在idea中的快捷键:psvm

    • springBoot的启动:

      SpringApplication.run(主程序类.class,main函数的参数);
      
    • Spring Boot将所有的功能场景都抽取出来,做成一个个的starter(启动器),只需要在项目里面引入这些starter,相关场景的所有依赖都会导入进来

    • 自定义第三方Bean:现实的java应用往往需要引入许多来自第三方的包,并且很有可能希望把第三方包的类对象也放入到Ioc容器中,这是@Bean注解就可以发挥作用了。

      eg:引入一个DBCP的数据源

      @Bean(name="dataSource")
      public DataSource getDataSource(){
         Properties pros=new Properties();
         pros.setProPerty("driver","com.mysql.jdbc.Driver");
         .....
         return dataSource;
      }
      

      说明:注解将会用“datasource”的名称作为Bean名称保存到IOC容器中

    • 依赖注入:@Autowired:会根据属性的类型找到对应的Bean进行注入,如果对应类型给的Bean不是唯一的,那么它会根据其属性名称和Bean的名称进行匹配,如果匹配得上,就会使用该Bean,如果还是无法匹配,就会抛出异常。

      注意:@Autowired是一个默认必须找到对应Bean的注解,如果不能确定其标注属性一定会存在,并且允许这个被标注的属性为null,则可以配置@Autowired的属性required为false.eg:

      @Autowired(required=false)
      
  • Bean的生命周期:

    • Bean定义
    • Bean初始化
    • Bean的生存期
    • Bean销毁
    资源定位 Bean定义 发布Bean定义 实例化 依赖注入
    例如@Component定义的扫描包 将Bean定义保存到BeanDefinition中 Ioc容易装载Bean定义 创建Bean示例对象 例如@Autowired注入各类资源

    注意:默认情况下Bean定义被发布到IOC容器之后,会继续去完成初

    始化,但有些Bean会收到变化因素的影响,这时我们希望是取出Bean时完成初始化和依赖注入,此时可将Component的配置项lazyInit设为true

    @ComponentScan(basepackage="",lazyInit=true)
    
  • Bean作用域:

    作用域类型 使用范围 作用域描述
    singleton 所有spring 应用 默认值,IOC容器中只存在单例
    prototype 所有spring 应用 每当从IOC容器中取出一个Bean,则创建一个新的Bean
    session Spring Web 应用 Http会话
    application Spring Web 应用 Web工程生命周期
    request Spring Web 应用 web工程单次请求
    globalSession Spring Web 应用 在一个全局的Http Session中,一个Bean对应一个实例
  • spring.profile.active:配置环境

  • Spring EL表达语言:可以拥有更为强大的运算规则来更好的装配Bean

    @Value("${database.driverName}") 
    String driver;
    
    @Value("#{T(System).currentTimeMilis()}")
    private Long initTime=null;
    
    @Value("#{beanName.str}")
    private String otherBeanProp=null;
    
    @Value("#{beanName.str?.toUpperCase()}")
    private String ortherBeanProp=null;
    
    @Value("#{beanName.str eq 'springBoot'}")
    
    • ${......}代表占位符:会读取上下文的属性值装配到属性中
    • {......}代表启动Spring表达式:具有运算功能

    • T(.......)代表引入类
    • beanName是spring Ioc容器Bean名称,str是其属性(获取其他的Spring Bean 属性来给当前的Bean属性赋值)
    • ?. :判断这个属性是否为null
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容