• (续)SSM整合之spring笔记(IOC 基于注解的自动装配@Autowired)(P091—P093)


     一 . 实验二:基于注解的自动装配

    ①场景模拟

    参考基于 xml 的自动装配
    第一步:
    UserController 中声明 UserService 对象
    1. //@Controller("controller")
    2. @Controller
    3. public class UserController {
    4. private UserService userService;
    5. }

    UserServiceImpl 中声明 UserDao 对象
    1. @Service
    2. public class UserServiceImpl implements UserService {
    3. private UserDao userDao;
    4. }

     第二步:在UserController里面有userService对象

    userService对象调用方法saveUser();   调用保存用户信息方法  userService.saveUser(); 

    1. @Controller
    2. public class UserController {
    3. private UserService userService;
    4. public void saveUser(){
    5. userService.saveUser();
    6. }
    7. }

     第三步:UserService接口里面创建方法    创建保存用户信息方法

    1. package com.atguigu.spring.service;
    2. public interface UserService {
    3. /**
    4. * 保存用户信息
    5. */
    6. void saveUser();
    7. }

     第四步:然后找到UserServiceImpl  对方法进行重写  Ctrl+O

    重写 调用userDao里面的saveUser();

    第五步:UseDao接口里面创建方法    创建保存用户信息方法

    1. public interface UserDao {
    2. /**
    3. * 保存用户信息
    4. */
    5. void saveUser();
    6. }

     

     第六步:找到Dao的实现类   进行方法重写

    1. @Repository
    2. public class UserDaoImpl implements UserDao {
    3. @Override
    4. public void saveUser() {
    5. System.out.println("保存成功");
    6. }
    7. }

     

     总结:

    第一步:UserController中声明UserService对象

                   在UserServiceImpl中声明UserDao对象

    第二步:在UserController里面 userService对象调用方法saveUser();   调用保存用户信息方法

    第三步:UserService接口里面创建方法    创建保存用户信息方法

    第四步:然后找到UserServiceImpl  对方法进行重写  Ctrl+O

    第五步:UseDao接口里面创建方法    创建保存用户信息方法

     第六步:找到Dao的实现类   进行方法重写

    @Autowired注解

    问题:如何实现自动装配的效果

    在成员变量上直接标记 @Autowired 注解即可完成自动装配,不需要提供 setXxx() 方法。以后我们在项 目中的正式用法就是这样。
    UserController
    1. @Controller
    2. public class UserController {
    3. @Autowired
    4. private UserService userService;
    5. public void saveUser(){
    6. userService.saveUser();
    7. }
    8. }

    UserServiceImpl
    1. @Service
    2. public class UserServiceImpl implements UserService {
    3. @Autowired
    4. private UserDao userDao;
    5. @Override
    6. public void saveUser() {
    7. userDao.saveUser();
    8. }
    9. }

     

    测试:

    1. public class IOCByAnnotationTest {
    2. /**
    3. * @Component:将类标识为普通组件
    4. * @Controller:将类标识为控制层组件
    5. * @Service:将类标识为业务层组件
    6. * @Repository:将类标识为持久层组件
    7. *
    8. * 通过注解+扫描所配置的bean的id,默认值为类的小驼峰,即类名的首字母为小写的结果
    9. * 可以通过标识组件的注解的value属性值设置bean的自定义的id
    10. *
    11. * @Autowired:实现自动装配功能的注解
    12. * 1、@Autowired注解能够标识的位置
    13. * a>标识在成员变量上,此时不需要设置成员变量的set方法
    14. * b>标识在set方法上
    15. * c>标识在为当前成员变量赋值的有参构造上
    16. * 2、@Autowired注解的原理
    17. * a>默认通过byType的方式,在IOC容器中通过类型匹配某个bean为属性赋值
    18. * b>若有多个类型匹配的bean,此时会自动转换为byName的方式实现自动装配的效果
    19. * 即将要赋值的属性的属性名作为bean的id匹配某个bean为属性赋值
    20. * c>若byType和byName的方式都无妨实现自动装配,即IOC容器中有多个类型匹配的bean
    21. * 且这些bean的id和要赋值的属性的属性名都不一致,此时抛异常:NoUniqueBeanDefinitionException
    22. * d>此时可以在要赋值的属性上,添加一个注解@Qualifier
    23. * 通过该注解的value属性值,指定某个bean的id,将这个bean为属性赋值
    24. *
    25. * 注意:若IOC容器中没有任何一个类型匹配的bean,此时抛出异常:NoSuchBeanDefinitionException
    26. * 在@Autowired注解中有个属性required,默认值为true,要求必须完成自动装配
    27. * 可以将required设置为false,此时能装配则装配,无法装配则使用属性的默认值
    28. */
    29. @Test
    30. public void test(){
    31. ApplicationContext ioc =new ClassPathXmlApplicationContext("spring-ioc-annotation.xml");
    32. // UserController userController = ioc.getBean("controller",UserController.class);
    33. UserController userController = ioc.getBean("userController",UserController.class);
    34. /* System.out.println(userController);
    35. UserService userService = ioc.getBean("userServiceImpl",UserService.class);
    36. System.out.println(userService);
    37. UserDao userDao = ioc.getBean("userDaoImpl",UserDao.class);
    38. System.out.println(userDao);*/
    39. userController.saveUser();
    40. }
    41. }

     

    保存成功说明UserController里面的userService已经被赋值,UserServiceImpl里面的userDao也被赋值了

    总结:加了自动装配@Autowired注解后,UserController里面的userService和UserServiceImpl里面的userDao被赋值

     @Autowired注解也可以标记在构造器和set方法上

    @Autowired注解标记在set方法上

    1. @Controller
    2. public class UserController {
    3. private UserService userService;
    4. @Autowired
    5. public void setUserService(UserService userService) {
    6. this.userService = userService;
    7. }
    8. public void saveUser(){
    9. userService.saveUser();
    10. }
    11. }

     

     @Autowired注解标记在有参构造器上

    1. //@Controller("controller")
    2. @Controller
    3. public class UserController {
    4. private UserService userService;
    5. @Autowired
    6. public UserController(UserService userService) {
    7. this.userService = userService;
    8. }
    9. /* public void setUserService(UserService userService) {
    10. this.userService = userService;
    11. }*/
    12. public void saveUser(){
    13. userService.saveUser();
    14. }
    15. }

     

     

    ③ @Autowired(原理)

    @Autowired注解的原理
    * a>默认通过byType的方式,在IOC容器中通过类型匹配某个bean为属性赋值
    byType:根据类型在ioc容器中找到一个和类型匹配的bean来为当前的属性自动进行赋值
    byName:把我们要赋值的属性的属性名,做为bean的id在IOC容器上去匹配到某一个bean来为当前的属性赋值
    * b>若有多个类型匹配的bean,此时会自动转换为byName的方式实现自动装配的效果
    * 即将要赋值的属性的属性名作为bean的id匹配某个bean为属性赋值
    

    先前的bean  

    通过注解在扫描  在ioc容器中已经有UserServiceImpl一个bean

    下面在加二个bean

    1. "1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xmlns:context="http://www.springframework.org/schema/context"
    5. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    6. <context:component-scan base-package="com.atguigu.spring">context:component-scan>
    7. <bean id="userService" class="com.atguigu.spring.service.impl.UserServiceImpl">bean>
    8. <bean id="userDao" class="com.atguigu.spring.dao.impl.UserDaoImpl">bean>
    9. beans>
    解释:
    

    在UserController里面要赋值叫做userService  而在xml里面也设置了一个bean也叫做userService 

    在UserServiceImpl里面使用了一个userDao,在xml里面也设置了一个bean也叫做userDao

    所以这里是自动转化为byName的方式实现自动装配的效果

    * c>若byType和byName的方式都无法实现自动装配,即IOC容器中有多个类型匹配的bean
    * 且这些bean的id和要赋值的属性的属性名都不一致,此时抛异常:NoUniqueBeanDefinitionException* 
    
    1. "1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xmlns:context="http://www.springframework.org/schema/context"
    5. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    6. <context:component-scan base-package="com.atguigu.spring">context:component-scan>
    7. <bean id="service" class="com.atguigu.spring.service.impl.UserServiceImpl">bean>
    8. <bean id="dao" class="com.atguigu.spring.dao.impl.UserDaoImpl">bean>
    9. beans>
    报错:
    Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.atguigu.spring.service.UserService' available: expected single matching bean but found 2: userServiceImpl,service
    
    
    
    * d>此时可以在要赋值的属性上,添加一个注解@Qualifier
    * 通过该注解的value属性值,指定某个bean的id,将这个bean为属性赋值
    解决办法
    
    1. @Controller
    2. public class UserController {
    3. @Autowired
    4. @Qualifier("userServiceImpl")
    5. private UserService userService;
    6. /* public UserController(UserService userService) {
    7. this.userService = userService;
    8. }*/
    9. /* public void setUserService(UserService userService) {
    10. this.userService = userService;
    11. }*/
    12. public void saveUser(){
    13. userService.saveUser();
    14. }
    15. }
     
     
    1. @Service
    2. public class UserServiceImpl implements UserService {
    3. @Autowired
    4. @Qualifier("userDaoImpl")
    5. private UserDao userDao;
    6. @Override
    7. public void saveUser() {
    8. userDao.saveUser();
    9. }
    10. }
    
    注意:若IOC容器中没有任何一个类型匹配的bean,此时抛出异常:NoSuchBeanDefinitionException
    忘记写@Service
    
    1. public class UserServiceImpl implements UserService {
    2. @Autowired
    3. // @Qualifier("userDaoImpl")
    4. private UserDao userDao;
    5. @Override
    6. public void saveUser() {
    7. userDao.saveUser();
    8. }
    9. }
    报错
    Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.atguigu.spring.service.UserService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    没有一个UserService所匹配的bean  此时就要找到UserService的实现加上@Service
    
    
    
    
    * 在@Autowired注解中有个属性required,默认值为true,要求必须完成自动装配
    * 可以将required设置为false,此时能装配则装配,无法装配则使用属性的默认值

     ④ @Autowired工作流程

     

     

    首先根据所需要的组件类型到 IOC 容器中查找
    能够找到唯一的 bean :直接执行装配
    如果完全找不到匹配这个类型的 bean :装配失败
    和所需类型匹配的 bean 不止一个
    没有 @Qualifier 注解:根据 @Autowired 标记位置成员变量的变量名作为 bean id 进行
    匹配
    能够找到:执行装配
    找不到:装配失败
    使用 @Qualifier 注解:根据 @Qualifier 注解中指定的名称作为 bean id 进行匹配
    能够找到:执行装配
    找不到:装配失败

     

    总结:

    /**
     * @Component:将类标识为普通组件
     * @Controller:将类标识为控制层组件
     * @Service:将类标识为业务层组件
     * @Repository:将类标识为持久层组件
     *
     * 通过注解+扫描所配置的bean的id,默认值为类的小驼峰,即类名的首字母为小写的结果
     * 可以通过标识组件的注解的value属性值设置bean的自定义的id
     *
     * @Autowired:实现自动装配功能的注解
     * 1、@Autowired注解能够标识的位置
     * a>标识在成员变量上,此时不需要设置成员变量的set方法
     * b>标识在set方法上
     * c>标识在为当前成员变量赋值的有参构造上
     * 2、@Autowired注解的原理
     * a>默认通过byType的方式,在IOC容器中通过类型匹配某个bean为属性赋值
     * b>若有多个类型匹配的bean,此时会自动转换为byName的方式实现自动装配的效果
     * 即将要赋值的属性的属性名作为bean的id匹配某个bean为属性赋值
     * c>若byType和byName的方式都无妨实现自动装配,即IOC容器中有多个类型匹配的bean
     * 且这些bean的id和要赋值的属性的属性名都不一致,此时抛异常:NoUniqueBeanDefinitionException
     * d>此时可以在要赋值的属性上,添加一个注解@Qualifier
     * 通过该注解的value属性值,指定某个bean的id,将这个bean为属性赋值
     *
     * 注意:若IOC容器中没有任何一个类型匹配的bean,此时抛出异常:NoSuchBeanDefinitionException
     * 在@Autowired注解中有个属性required,默认值为true,要求必须完成自动装配
     * 可以将required设置为false,此时能装配则装配,无法装配则使用属性的默认值
     */

     

     

     

     

     

     

     

     

     

     
     
     
     
     
     
     
     

     
     

  • 相关阅读:
    K8S存储总结&持久化存储解决方案(以NFS为例)
    界面控件Kendo UI for jQuery R3 2023 - 发布全新金字塔图表类型
    Spring数据库数据源JDBC连接池连接MySQL的超时问题
    机器学习——第五章 神经网络
    性能评测 | GreatDB VIP PLUGIN方案 VS MySQL InnoDB Cluster高可用方案
    SpringBoot+Vue2项目解决前后端跨域方案
    24.bytebuf创建
    python+selenium的web自动化之针对上传操作的实现方案
    图像形态学操作(连通性、腐蚀、膨胀)
    【Java核心知识】idea项目编译错误排查思路
  • 原文地址:https://blog.csdn.net/m0_59281987/article/details/127672896