Spring Boot教程 – 直观地理解Spring容器

       在一个系统里,可能有多个业务部分,比如用户服务,订单服务,数据服务等等,在代码里,这些服务也许分布在多个类中,可能叫做UserService或者OrderService等等。为了简便,我们假设系统里有A、B、C、D四个类,他们有如下的依赖关系:

         简单来说,D是B的成员,A和B是C的成员。

         当你的系统规模扩大了以后,有上百个对象需要初始化以及设置依赖的时候,复杂度就直线上升了。

       系统类的对象越多,依赖关系越复杂

       为了降低复杂度,减少他们之间的耦合,这个时候我们就需要用上Spring容器了。程序里的对象都可以扔到容器里,对象只需要告诉容器它需要哪些依赖就行,容器自动初始化好并给它。比如上面ABCD那个例子,C告诉容器它需要A和B,B告诉容器它需要D,这样ABCD四个对象都可以扔到容器里了,当你想用C的时候,就从容器里面拿出来,这时候C的成员就已经包含了A和B了(我们目前只讨论单例的情况,就是一个类只有一个对象)。

      容器通过“配置”来了解对象之间的依赖关系。

       在Spring框架里,ApplicationContext就代表了容器(又叫应用程序上下文),容器里的对象,又叫Bean。

       Bean是啥?

      1、Java面向对象,对象有方法和属性,那么就需要对象实例来调用方法和属性(即实例化);

      2、凡是有方法或属性的类都需要实例化,这样才能具象化去使用这些方法和属性;

      3、规律:凡是子类及带有方法或属性的类都要加上注册Bean到Spring IoC的注解

      4、把Bean理解为类的代理或代言人(实际上确实是通过反射、代理来实现的),这样它就能代表类拥有该拥有的东西了

     5、我们都在微博上@过某某,对方会优先看到这条信息,并给你反馈,那么在Spring中,你标识一个@符号,那么Spring就会来看看,并且从这里拿到一个Bean或者给出一个Bean。

       注解分为两类:

      1、一类是使用Bean,即是把已经在xml文件中配置好的Bean拿来用,完成属性、方法的组装;比如@Autowired , @Resource,可以通过byTYPE(@Autowired)、byNAME(@Resource)的方式获取Bean;

     2、一类是注册Bean,@Component , @Repository , @ Controller , @Service , @Configration这些注解都是把你要实例化的对象转化成一个Bean,放在IoC容器中,等你要用的时候,它会和上面的@Autowired , @Resource配合到一起,把对象、属性、方法完美组装。

       @Bean是啥?

       看看源码:

     @Bean
     public MyBean myBean() {
         // instantiate and configure MyBean obj
         return obj;
    }

         意思是@Bean明确地指示了一种方法,什么方法呢——产生一个bean的方法,并且交给Spring容器管理;从这我们就明白了为啥@Bean是放在方法的注释上了,因为它很明确地告诉被注释的方法,你给我产生一个Bean,然后交给Spring容器,剩下的你就别管了。

        小总结:

        1、凡是子类及带属性、方法的类都注册Bean到Spring中,交给它管理;

         2、@Bean 用在方法上,告诉Spring容器,你可以从下面这个方法中拿到一个Bean

 

        另外对以上一些注解的另外一种表述:

          先上源程序图:

图中显示了项目的源码结构、程序的入口、配置以及依赖。

上图写出了ABCD的源码。

       配置文件是Config.java,它有一个@Configuration注解,这表明Config类是配置类。它还有另外一个注解@ComponentScan,这个注解表示容器应该去扫描程序的代码,看看那些组件应当被初始化为Bean。哪些类会被初始化为Bean呢?我们看看ABCD的源码,发现他们各自都有注解@Component,这个注解就表示了它所在的类是组件,需要初始化Bean。C和B的成员变量都用@Autowired注解来修饰,这样容器就知道他们都依赖哪些Bean了,ABCD的对象都生成好之后,容器就把D对象赋值给B的成员,把A和B的对象赋值给C的成员。

        如果你运行程序,会发现输出的结果是true,也就是C里的A成员不为空。这样你是不是就理解了Spring容器的作用了呢?你的程序不必再在ABCD的外部去设置他们的依赖了,反而只需要在ABCD的类的内部指明依赖就行,这个从外而内的过程就是控制反转(IoC,Inversion of Control),控制权交给了Spring容器,Spring容器也叫IoC容器。你还可能听过依赖注入(DI,Dependency Injection),如果你看网上文章没明白,权当他们是一样的好了。

       对于开源库,他们的类肯定没有@Component注解,这样肯定不能通过扫描来加入容器。那就需要写点代码了。Config类中有一个objectMapper方法,返回了一个ObjectMapper对象(ObjectMapper是Jackson的关键类),objectMapper方法有个@Bean注解,表示返回的对象会加入到容器中。ObjectMapper对象可以在objectMapper方法里,进行一些修改呀,配置呀等等。

       这个时候ObjectMapper对象还没人用,如果ABCD任何一个类想用,只需要在类中加一个成员@Autowired ObjectMapper objectmapper;,Spring容器会自动把ObjectMapper对象赋值到这个成员上。非常方便,尤其是在大项目里,类非常多,一行代码就把你需要的对象拿过来用,简直爽的不行。在实践中,依赖的类常常是个接口,使用者只调用接口就行,至于容器给它哪种实现并不重要,这个逻辑在“配置”里就可以控制。这样,程序的耦合度进一步减小了。

        在我们之前运行第一个Spring Boot应用的时候,我们曾经添加了一个控制器,他有个@Controller注解,这个注解相当于一个特殊的@Component,只不过@Controller表示当前的组件是用来处理网络请求的。类似的还有,@Service用来表示业务相关的组件,@Repository用来表示数据获取相关的组件。他们都是通过自动扫描放到Spring容器中的。

 

 

 

 

 

 

 

 

 

 

 

 

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值