Spring Ioc&DI(二)

发布于:2025-09-10 ⋅ 阅读:(19) ⋅ 点赞:(0)

前言:

上篇博客简单了解Ioc&DI的概念以及使用,这篇博客内容是Ioc详解和多种注解的具体使用


Ioc详解

前文我们所了解到的Ioc控制反转,就是将对象交给Spring的Ioc容器,由Ioc容器创建和管理对象,这一过程也成为Bean的存储

什么是Bean?

交由Spring容器进行存储管理的对象,统称为Bean。

Bean的特点:

①Bean的创建、销毁、依赖注入都由Spring控制,而不是开发者手动处理

②Bean的定义——无论是XML、@Component注解还是Java配置类注解@Configuration,都可以声明Bean的变量

③Bean一般情况下默认是单例模式

要将对象交给Spring进行管理,需要在其类上面添加注解,能够实现这个目的的注解分为两类——类注解以及方法注解

类注解:@Component  @Controller  @Configuration   @Service   @Repository

方法注解:@Bean


@Component是通用的Bean存储注解,由于开发会对整个项目进行代码分成,@Component衍生出对应的层所使用的注解,例如控制层衍生出@Controller(Web层),类似的注解还有@Service(业务逻辑层)以及@Repository(数据访问层DAO)

@Controller(控制器存储)

使用@Controller注解的方式进行Bean的存储

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

既然会存储Bean了,由该怎么获取Bean呢?——使用ApplicationContext进行获取

@SpringBootApplication
public class SpringIocDemoApplication {
     public static void main(String[] args) {
         //获取Spring上下⽂对象
         ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);                                   
         //从Spring上下⽂中获取对象
         UserController userController = context.getBean(UserController.class);
         //使⽤对象
         userController.sayHi();
 }
}

把注解去掉,Spring扫描不到Bean就会报错

@Service(服务存储)

类似上述@Controller的存储方式进行存储

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

依旧使用ApplicationContext获取类,由类调用方法去获取Bean

@SpringBootApplication
public class SpringIocDemoApplication {
 public static void main(String[] args) {
     //获取Spring上下⽂对象
     ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);
     //从Spring中获取UserService对象
     UserService userService = context.getBean(UserService.class);
     //使⽤对象
     userService.sayHi();
     }
}

去掉注解依旧会扫描不到Bean,其实@Service功能上和@Component没差别,就是为了代码客观性满足应用分层的设计理念


方法注解@Bean

不同于上述的类注解,方法注解则是添加在类的构造方法上,而且方法注解往往需要搭配类注解进行使用

@Component
public class BeanConfig {
     @Bean
     public User user(){
         User user = new User();
         user.setName("zhangsan");
         user.setAge(18);
         return user;
     }
}

获取Bean

@SpringBootApplication
public class SpringIocDemoApplication {
     public static void main(String[] args) {
         //获取Spring上下⽂对象
         ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);
         //从Spring上下⽂中获取对象
         User user = context.getBean(User.class);
         //使⽤对象
         System.out.println(user);
     }
}

现在有一个很明显的问题,一个类可以有多个构造方法,那我能不能有多个Bean?

答案是可以的,但是Bean一般是单例模式,定义多个Bean在扫描获取Bean的时候就需要通过具体的Bean的名称去获取

@Component
public class BeanConfig {
     @Bean
     public User user1(){
         User user = new User();
         user.setName("zhangsan");
         user.setAge(18);
         return user;
     }
     @Bean
     public User user2(){
         User user = new User();
         user.setName("lisi");
         user.setAge(19);
         return user;
     }

}

通过ApplicationContext获取Bean,报错信息表示在扫描的时候预期只会匹配一个Bean,但是目前有两个

这是直接用getBean获取Bean会产生的错误,通过具体的Bean名称去获取Bean就不会报错了

@SpringBootApplication
public class SpringIocDemoApplication {
     public static void main(String[] args) {
     //获取Spring上下⽂对象
      ApplicationContext context = 
      SpringApplication.run(SpringIocDemoApplication.class, args);
     //根据bean名称, 从Spring上下⽂中获取对象
      User user1 = (User) context.getBean("user1");
      User user2 = (User) context.getBean("user2");
      System.out.println(user1);
      System.out.println(user2);
 }
}

结果如下

重命名Bean

@Bean({“Bean名”}),单个Bean名可以直接@Bean("Bean名")

public class User{
    @Bean(name = {"u1","user1"})
    public User user1(){
         User user = new User();
         user.setName("zhangsan");
         user.setAge(18);
         return user;
    }
}

可以直接通过使用u1来获取对象

@SpringBootApplication
public class SpringIocDemoApplication {
     public static void main(String[] args) {
         //获取Spring上下⽂对象
         ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);
         //从Spring上下⽂中获取对象
         User u1 = (User) context.getBean("u1");
         //使⽤对象
         System.out.println(u1);
 }

扫描路径

Bean类要想被扫描,所在的包就必须要在Spring的扫描路径下。Spring的扫描路径默认是SpringBoot启动类所在的包以及子包。