Spring IoC/DI

目录

一,IoC控制反转

1,Bean的存储:

(1),类注解:

(2),方法注解:

2,@Controller

3,@Bean

4,路径扫描:

二,DI依赖注入

(1)属性注入

(2)构造方法注入

(3)Setter注入

(4)三种方法的优缺点:

(5)@Autowired存在的问题

@Primary(Spring提供)

@Qualifier(Spring提供)

@Resource(JDK解决方案)

(6)@Autowired和@Resource的区别:

(7)Autowired的装配顺序:


IoC&DI是Spring的两个核心思想,Spring是一个包含了众多工具的IoC容器

一,IoC控制反转

IoC(inversion of Control)控制反转,也就是说spring是一个"控制反转"的容器,这里的控制权指的是bean的控制权,Spring管理的对象称之为bean,之前对象的使用方,创建对象.对象的控制权在对象的使用方手里.控制反转是指对象的控制权交给了Spring

1,Bean的存储:

有两类方法:

(1),类注解:

@Controller,@Service,@Responsitory,@Component,@Configuratic

(2),方法注解:

@Bean

--------------------------------------------

2,@Controller

程序开发⼈员不需要为bean指定名称(BeanId),如果没有显式的提供名称(BeanId),Spring容器将为该 bean⽣成唯⼀的名称. 命名约定使⽤Java标准约定作为实例字段名.也就是说,bean名称以⼩写字⺟开头,然后使⽤驼峰式 ⼤⼩写.也有⼀些特殊情况,当有多个字符并且第⼀个和第⼆个字符都是⼤写时,将保留原始的⼤⼩写.这些规则 与java.beans.Introspector.decapitalize (Spring在这⾥使⽤的)定义的规则相同

        //法一:
		ConfigurableApplicationContext context= SpringApplication.run(SpringIocApplication.class, args);
        #context可以理解成Spring容器(Spring应用的上下文)
		UserController bean = context.getBean(UserController.class);
		bean.say();
		//法二:
		UserController userController = (UserController) context.getBean("userController");
		userController.say();
		//法三:
		UserController userController1 = context.getBean("userController", UserController.class);
		userController1.say();

		System.out.println(bean);
		System.out.println(userController);
		System.out.println(userController1);

地址一样说明对象是同一个(单例模式)

@Service,@Responsitory,@Component,@Configuratic与@Controller的用法类似,这些注解和应用层是呼应的,例如:控制层使用的就是@Controller,业务逻辑层@Service,数据访问层为@Responsitory,配置层为@Configuratic,不同的层次对应不同的注解,由此程序员看到不同的注解就可以了解当前类的用途.

3,@Bean

作用:

(1)一个类需要多个对象

(2)使用外部类,没有办法对类进行注解

注:Bean的指定名称就是方法名.

外部类:

//外部类
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserInfo {
    private String name;
    private Integer age;
}

创建一个对象并交给Spring

在Spring框架的设计中,⽅法注解 @Bean 要配合类注解才能将对象正常的存储到Spring容器中

@Component
public class UserInfoComponent {
    @Bean
    public UserInfo userInfo(){
        return new UserInfo("zhangsan",12);

    }
}

用Bean创建多个对象

@Component
public class UserInfoComponent {
    @Bean
    public UserInfo userInfo(){
        return new UserInfo("zhangsan",12);

    }

    @Bean
    public UserInfo userInfo1(){
        return new UserInfo("lisi",17);

    }
}

@Bean重命名

@Bean(name = {"zhangsan","userInfo"})
    public UserInfo userInfo(){
        return new UserInfo("zhangsan",12);

    }

综合上述代码使用:

public static void main(String[] args) {
		ConfigurableApplicationContext context= SpringApplication.run(SpringIocApplication.class, args);
		Object userInfo = context.getBean("userInfo");
		System.out.println(userInfo);
		Object userInfo1 = context.getBean("zhangsan");
		System.out.println(userInfo);
		Object userInfo2 = context.getBean("userInfo1");
		System.out.println(userInfo2);

	}

4,路径扫描:

想要让Bean生效,还要配置扫描路径,让Spring扫描到,让Spring扫描到这些就需要通过注解@ComponentScan来配置扫描路径.上述代码错误的原因就是当前只扫描了(com.ABdolphin.ioc是Spring默认的扫描类,我们创建的类都要放到这个路径底下)com.ABdolphin.ioc.Contraller;下方的代码,但是但是Bean在com.ABdolphin.ioc.component,所以扫描不到:

那为什么前⾯没有配置@ComponentScan注解也可以呢? @ComponentScan 注解虽然没有显式配置,但是实际上已经包含在了启动类声明注解 @SpringBootApplication 中了

二,DI依赖注入

有三种方式:

(1)属性注入

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

@Controller
public class UserController {
    @Autowired
    private UserService userService;
    public void say(){
        userService.say();
       System.out.println("UserController say...");
    }
}

(2)构造方法注入

@Controller
public class UserController {
    private UserService userService;

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

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

如果有多个构造参数,这时会默认使用无参数的构造函数,所以就需要我们将默认使用的构造函数设置为有参数的构造函数,需要使用注解 @Autowired

@Controller
public class UserController {
    private UserService userService;

    public UserController() {
    }
    @Autowired      #底层使用的反射,当调用构造方法时,发现没有给值,就自己从Spring容器中获取
    public UserController(UserService userService) {
        this.userService = userService;
    }

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

交给Spring管理的对象,如果有参数,这个参数可以自己指定,如果没有指定,Spring会根据名称或者类型,从容器中查找,并注入进来

(3)Set方法注入

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

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

(4)三种方法的优缺点:

属性注入:

优点:简单

缺点只能用于IoC容器,不能注入一个final修饰的属性

构造函数注入(Spring4.X推荐):

Spring Boot 3.X对应的是Spring 6.X

优点:可以注入final修饰的属性,注入的对象不会被修改,通用性好,构造方法是JDK支持的,所以任何框架都是支持的

缺点:注入多个对象的时候,代码会比较繁琐

setter注入(Spring3.X推荐):

优点,缺点:可以调用setter方法,因此注入的对象是可以被修改的

(5)@Autowired存在的问题

同样类型有多个对象时,按对象名称来匹配.当一种类型只有一个对象时,不管名称,直接注入进来

当有多个同样类型有多个对象,且调用的名称与对象的名称均不相同,这时可以使用以下几种方案:

@Primary(Spring提供)

   @Primary
    @Bean
    public UserInfo userInfo1(){
        return new UserInfo("lisi",17);

    }

@Qualifier(Spring提供)

写法一:

@Component
public class UserComponent {
    @Qualifier("userInfo2")
    @Autowired
    private UserInfo ui;
    public void say(){
        System.out.println("UserComponent say...");
        System.out.println(ui);
    }
}

写法二:

 @Bean
    public String name(){
        return "test";
    }
    /*@Primary*/
    @Bean
    public String name2(){
        return "test2";
    }
    
    @Bean
    public UserInfo userInfo2(@Qualifier("name2")String name3){
        return new UserInfo(name3,17);

    }

@Resource(JDK解决方案)

@Component
public class UserComponent {

    @Resource(name = "userInfo2")
    private UserInfo ui;
    public void say(){
        System.out.println("UserComponent say...");
        System.out.println(ui);
    }
}

(6)@Autowired和@Resource的区别:

1,@Autowired是根据类型进行匹配的,@Resource是根据名称进行匹配的[并不准确](@Autowired优先按照类型匹配,如果有相同类型的多个对象,就会根据名称匹配.@Resource前提也是按照类型匹配的)

2,@Autowired是spring框架提供的注解,⽽@Resource是JDK提供的注解

(7)Autowired的装配顺序:

Spring framework,SpringMVC,SpringBoot的联系和区别:

Spring framework:管理对象,以及对象之间的依赖关系,面向切面编程,数据库事务管理...

SpringMVC是一个Spring子框架,是一个web框架

SpringBoot:springBoot是对Spring的一个封装,为了简化Spring应用开发而出现的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值