Spring IoC

目录

一.IoC

 1.1什么是IoC?

1.2 loC容器具备以下优点: 

      二.DI

三.Bean的储存(五大注解)

3.1 @Controller(控制器存储) 

3.2 @Service(服务存储) 

3.3 @Repository(仓库存储) 

 3.4 @Component  (组件存储) 

 3.5 @Configuration(配置存储)

3.6为什么要这么多类注解?

3.6.1方法注解 @Bean

小总结:

四.DI 详解 

4.1属性注入

4.1构造方法注入 

4.2 Setter方法注入  

4.3三种注⼊优缺点分析:

​编辑 


一.IoC

               通过这篇博客 Spring Web MVC-优快云博客 我们已经了解Spring是一个开源框架,他可以让我们开发更加简单。

                用具体的话概括Spring的话,就是:Spring是包含了众多工具方法的IoC容器

 1.1什么是IoC?

           loC是Spring的核心思想

     

          其实loC我们在前面已经使用了,在类上面添加@RestController@Controller注解,就是把这个对象交给Spring管理,Spring 框架启动时就会加载该类.把对象交给Spring管理,就是loC思想. 

        IoC: Inversion of Control (控制反转) 也就是说 Spring 是⼀个"控制反转"的容器
                什么是控制反转呢?也就是控制权反转.什么的控制权发生了反转?获得依赖对象的过程被反转了也就是说,当需要某个对象时,传统开发模式中需要自已通过new创建对象,现在不需要再进行创建,把创建对象的任务交给容器,程序中只需要依赖注入(DependencyInjection,Dl)就可以了,这个容器称为:loC容器。Spring是一个loC容器,所以有时Spring也称为Spring容器.

        控制反转是一种思想,生活中处处体现

           例如:⾃动驾驶, 传统驾驶⽅式, ⻋辆的横向和纵向驾驶控制权由驾驶员来控制, 现在交给了驾驶⾃ 动化系统来控制, 这也是控制反转思想在⽣活中的实现

举个案例:

        需求:造一辆车 

   传统开发的实现思路:

        先设计轮子(Tire),然后根据轮子的大小设计底盘(Bottom),接着根据底盘设计车身(Framework),最后根据车身设计好整个汽车(Car)。这里就出现了一个"依赖"关系:汽车依赖车身,车身依赖底盘,底盘依赖轮子.

问题是:当最底层代码改动之后,整个调用链上的所有代码都需要修改.  (耦合高

IoC开发实现思路:

 


改进之后的控制权发生的反转,不再是使用方对象创建并控制依赖对象了,而是把依赖对象注入将当前对象中,依赖对象的控制权不再由当前类控制了.

优势在于 耦合低,这样的话,即使依赖类发生任何改变,当前类都是不受影响的,这就是典型的控制反转,也就是loC的实现思想。从⽽实现了更加灵活、通⽤的程序设计了

1.2 loC容器具备以下优点: 

资源不由使用资源的双方管理,而由不使用资源的第三方管理,这可以带来很多好处。第一,资源集中管理,实现资源的可配置和易管理。第二,降低了使用资源双方的依赖程度,也就是我们说的耦合度。

  1. 资源集中管理:loC容器会帮我们管理一些资源(对象等),我们需要使用时,只需要从loC容器中去取就可以了
  2. 我们在创建实例的时候不需要了解其中的细节,降低了使用资源双方的依赖程度,也就是耦合度。

      二.DI

        DI:(依赖注入)

       容器在运行期间,动态的为应用程序提供运行时所依赖的资源,称之为依赖注入。

        loC是一种思想,也是"目标",而思想只是一种指导原则,最终还是要有可行的落地方案,而DI就属于具体的实现。所以也可以说,DI是loC的一种实现

既然Spring是一个loC(控制反转)容器,作为容器,那么它就具备两个最基础的功能:

Spring 容器管理的主要是对象,这些对象,我们称之为"Bean".

三.Bean的储存(五大注解)

共有两类注解类型实现:

  1.  类注解:@Controller  @Service  @Component  @Repository  @Configuration                    ( 注意:如果类名前两个字符大写,则bean的名称是类名本身)
  2.  方法注解:@Bean  (Bean名就是方法名)

3.1 @Controller(控制器存储) 

 使用@Controller存储 bean的代码如下 :

@Controller //将对象存储到Spring中
public class UController {
    public void sayHi(){
        System.out.println(" hi  UController");
    }
}

如何判断是否存到容器当中了呢

下面尝试从Spring容器中获取对象 (共有三种方式):

读取 bean 的代码: @SpringBootApplication 

@SpringBootApplication
public class SpringIocDemoApplication {

    public static void main(String[] args) {
        //获取spring上下文对象
        ApplicationContext run = SpringApplication.run(SpringIocDemoApplication.class, args);
        /*
        * 常用获取bean的方法(三种)
        * 输出三种方式,结果证明地址一样,对象一样
        * */
        //方式一:根据类型,从Spring上下⽂中获取对象
        userController bean = run.getBean(userController.class);
        bean.sayHi();
        System.out.println(bean);

        //方式二:根据bean名,从Spring上下⽂中获取对象
        userController bean1 = (userController)run.getBean("userController");
        bean1.sayHi();
        System.out.println(bean1);

        //方式三://根据bean类型+名称, 从Spring上下⽂中获取对象
        userController bean2 = run.getBean("userController", userController.class);
        bean2.sayHi();
        System.out.println(bean2);
    }
}

 

3.2 @Service(服务存储) 

使⽤ @Service 存储 bean 的代码如下所⽰:
@Service
public class UserService {
    public void sayHi(){
        System.out.println("Hi  UserService");
    }
}

从Spring容器中获取对象
 public static void main(String[] args) {
        //获取spring上下文对象
        ApplicationContext run = SpringApplication.run(SpringIocDemoApplication.class, args);
        //方式一:根据类型,从Spring上下⽂中获取对象
        UserService userService = run.getBean(UserService.class);
        userService.sayHi();
        System.out.println(userService);
}

3.3 @Repository(仓库存储) 

使⽤ @Repository 存储 bean 的代码如下所⽰:
@Repository
public class UserRepository {
    public void sayHi(){
        System.out.println("Hi   UserRepository");
    }
}

从Spring容器中获取对象

  public static void main(String[] args) {
        //获取spring上下文对象
        ApplicationContext run = SpringApplication.run(SpringIocDemoApplication.class, args);
        //方式一:根据类型,从Spring上下⽂中获取对象
        UserRepository userRepository = run.getBean(UserRepository.class);
        userRepository.sayHi();
        System.out.println(userRepository);
}

 3.4 @Component  (组件存储) 

使⽤ @Component存储 bean 的代码如下所⽰:


@Component
public class ComPonent {
    public void sayHi(){
        System.out.println("Hi   ComPonent");
    }
}

从Spring容器中获取对象:

    public static void main(String[] args) {
        //获取spring上下文对象
        ApplicationContext run = SpringApplication.run(SpringIocDemoApplication.class, args);
        //方式一:根据类型,从Spring上下⽂中获取对象
        UserComPonent UserComPonent = run.getBean(UserComPonent.class);
        UserComPonent.sayHi();
        System.out.println(UserComPonent);
}

 3.5 @Configuration(配置存储)

使⽤ @Configuration存储 bean 的代码如下所⽰:

@Configurable
public class UserConfiguration {
    public void sayHi(){
        System.out.println("Hi   UserConfiguration");
    }
}

从Spring容器中获取对象

  public static void main(String[] args) {
        //获取spring上下文对象
        ApplicationContext run = SpringApplication.run(SpringIocDemoApplication.class, args);
        //方式一:根据类型,从Spring上下⽂中获取对象
        UserConfiguration userConfiguration = run.getBean(UserConfiguration.class);
        userConfiguration.sayHi();
        System.out.println(userConfiguration);
  }

3.6为什么要这么多类注解?

这个也是和咱们前面讲的应用分层是呼应的.让程序员看到类注解之后,就能直接了解当前类的用途。

  • @Controller:控制层,接受请求,对请求进行处理,并进行响应
  • @Servie:业务逻辑层,处理具体的业务逻辑
  • @Repository:数据访问层,也称为持久层,负责数据访问操作
  • @Configuration:配置层,处理项目中的一些配置信息                                                    这四个类全是@Component的衍生类,功能实现上,除了@Controller类其他是可以混用的(不推荐)

 

3.6.1方法注解 @Bean

类注解是添加到某个类上的,但是存在俩个问题:

  1. 使用外部包里的类,没办法添加类注解
  2. 一个类中,需要多个对象,

以上两种场合,我们就需要使用方法注解@Bean 必须搭配五大类使用

 注意:

        只有在五大注解下@bean才会生效 , 查看启动类所在的目录及其子孙目录

        在获取对象时 ,发现有两个或多个时,可以采用bean名+类名,来获取对象

小总结:

程序被Spring管理,需要具备以下条件:
1.被Spring扫描到(默认扫描路径是 启动类所在的目录,包含子目录)


2.需要配置五大注解和@Bean使用

四.DI 详解 

依赖注入是一个过程,是指IoC容器在创建Bean时,去提供运行是所以来的资源,而资源指的就是对象,需要使用@Autowired这个注解,来完成依赖注入。

简单来说,就是把对象取出来放到某个类的属性中

Spring提供了三种方式进行依赖注入:

  1. 属性注入(Field Injection)
  2. 构造方法注入 (Constructor Injection)
  3. Setter注入 (Setter Injection)                 

                                                                           

4.1属性注入

 演示 属性注⼊是使⽤ @Autowired 实现的,将 Service 类注⼊到 Controller 类中

 注意:无法注入一个final修饰的属性       

Service 代码如下:

@Service
public class UserService {
    public void sayHi(){
        System.out.println("Hi  UserService");
    }
}

Controller 代码如下: 

@Controller //将对象存储到spring中
public class UserController {
    //注入方法一:屬性注入
    @Autowired
    public UserService userService;
    
    public void sayHi(){
        System.out.println("Hi   UserController");
    }
}
获取 Controller 中的 sayHi⽅法:

4.1构造方法注入 

  • 如果类中只有一个构造方法,@Autowired注解可以省略,
  • 如果类中有多个构造方法,那么需要@Autowired来指定到底使用哪个构造方法              
  • 构造函数规范:   如果添加构造函数,把无参构造函数显示添加
@Controller //将对象存储到spring中
public class UserController {
    //注入方法二:构造方法注入

    public UserService userService;
    @Autowired
    public UserController(UserService userService) {
        this.userService = userService;
    }

    public void sayHi(){
        System.out.println("Hi   UserController");
        userService.sayHi();
    }
}

4.2 Setter方法注入  

Setter注入和属性的Setter方法实现类似,只不过在设置set方法的时候需要加上@Autowired注解

@Controller //将对象存储到spring中
public class UserController {
    //注入方法三:Setter方法注入

    public UserService userService;
   
    public UserController(UserService userService) {
        this.userService = userService;
    }
    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    public void sayHi(){
        System.out.println("Hi   UserController");
        userService.sayHi();
    }
}

 

当程序中同一个类型有多个对象时,使用@AutoWired会报错(一些情况下) 解决方法:

Spring提供了以下⼏种解决⽅案:
  • @Primary注解:当存在多个相同类型的Bean注入时,加上@Primary注解,来确定默认的实现 
  • @Qualifier注解:指定当前要注入的bean对象。在@Qualifier的value属性中,指定注入的bean的名称。@Qualifier注解不能单独使⽤,必须配合@Autowired使⽤
  • 使用@Resource注解:是按照bean的名称进行注入。通过name属性指定要注入的bean的名称。
       解决思想:指定Bean的名称
                       指定Bean

 @Autowird与@Resource的区别

 

4.3三种注⼊优缺点分析:

 

Autowired装配顺序 :

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值