Spring Ioc&DI(三)

发布于:2025-09-12 ⋅ 阅读:(22) ⋅ 点赞:(0)

DI详解

DI的意义是容器在创建Bean的时候能够提供依赖对象进行使用

DI的具体使用有三种注入方式:属性注入,方法构造注入,Setter注入

属性注入

属性注入是通过注解@Autowired实现将Bean的实例注入到另一个Bean的实例中

例如,我有一个类由@Service进行Bean管理,现在我要将Service中的实例注入到Controller中

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

Controller类,将Service中的Bean实例通过@Autowired进行注入

@Controller
public class UserController {
 //注⼊⽅法1: 属性注⼊
     @Autowired
     private UserService userService;
     public void sayHi(){
         System.out.println("hi,UserController...");
         userService.sayHi();
    }
}

在启动类实例化controller,调用其中的方法看看会是什么结果

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

我们可以观察到在将Service中的Bean实例注入到Controller的Bean实例后,两个Bean实例产生了依赖关系,后续实例化Controller的实例调用方法的时候将Service实例中的方法也有执行

构造方法注入

构造方法注入就是使用@Autowired注解在构造方法中进行Bean实例注入

@Controller
public class UserController {
 //注⼊⽅法: 构造方法注⼊
     private UserService userService;
    
     @Autowired
     public UserController(UserService userService)
    {
        this.userService = userService;
    }


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

Setter注入

Setter注入和属性的Setter方法实现类似,就是需要添加@Autowired注解

@Controller
public class UserController {
 //注⼊⽅法: Setter注⼊
     private UserService userService;
    
     @Autowired
     public void setUserService(UserService userService)
    {
        this.userService = userService;
    }


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

三种注入方式的区别:

属性注入——优点:简洁,用起来方便。缺点:只能用于Ioc容器,无法注入final定义的属性

构造方法——优点:通用性强——因为构造方法是JDK支持的;会对注入对象进行初始化且注入的对象不会被修改,还能注入被final定义的属性     

缺点:注入多个对象的时候会比较繁琐,需要频繁重新写构造方法

Setter注入——优点:方便在类实例之后进行配置或者注入  缺点:面临setter方法被频繁调用导致注入对象被修改的风险,不能注入final定义的变量

@Autowired存在的问题

如果遇到一个依赖中有多个Bean,单纯引用@Autowired进行注入会存在问题,依赖对象交给Ioc管理的Bean究竟是哪个?(无特殊声明,Bean默认是单例模式)

为了解决这一个问题,延伸出@Resource注解,在依赖注入时当依赖对象有多个Bean开发者更多的时选择使用@Resource,通过name属性来指定依赖对象中对应的Bean,这是最为干脆的解决方法

@Controller
public class UserController {
     @Resource(name = "user2")
     private User user;
     public void sayHi(){
         System.out.println("hi,UserController...");
         System.out.println(user);
     }
    }

还有一个方法就是——既然依赖对象有多个Bean,那么开发者直接指定其中的一个Bean作为依赖注入时默认使用的Bean,这个注解就是@Primary和@Qualifier

@Component
public class BeanConfig {
     @Primary //指定该bean为默认bean的实现
     @Bean("u1")
     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;
     }
}

@Qualifier和@Primary的区别就在于前者需要和@Autowired搭配使用,且前者是在注入的时候进行声明要指定哪个Bean作为注入的Bean,后者是在依赖对象中对Bean进行设置

@Controller
public class UserController {
     @Qualifier("user2") //指定bean名称
     @Autowired
     private User user;
         public void sayHi(){
         System.out.println("hi,UserController...");
         System.out.println(user);
     }
}

经典面试题:@Autowired和@Resource的区别?

①@Autowired是Spring框架提供的注解,@Resource是JDK提供的注解

②@Autowired是按照类型进行注入,@Resource是根据name来进行注入,相比于前者,后者更支持更多的参数设置


网站公告

今日签到

点亮在社区的每一天
去签到