• Spring--基于注解管理bean


    基于注解管理bean

    实验一:标记与扫描

    1. 注解
      和 XML 配置文件一样,注解本身并不能执行,注解本身仅仅只是做一个标记,具体的功能是框架检测到注解标记
      的位置,然后针对这个位置按照注解标记的功能来执行具体操作。
      本质上:所有一切的操作都是Java代码来完成的,XML和注解只是告诉框架中的Java代码如何执行。

    举例:元旦联欢会要布置教室,蓝色的地方贴上元旦快乐四个字,红色的地方贴上拉花,黄色的地方贴上气球。
    在这里插入图片描述
    班长做了所有标记,同学们来完成具体工作。墙上的标记相当于我们在代码中使用的注解,后面同学们做的工作,相当于框架的具体操作。

    1. 扫描
      Spring 为了知道程序员在哪些地方标记了什么注解,就需要通过扫描的方式,来进行检测。然后根据注解进行后
      续操作。

    2. 新建Maven Module
      在这里插入图片描述

    3. 创建Spring配置文件

    4. 标识组件常用的注解
      @Component:将类标识为普通组件
      @Controller:将类标识为控制层组件
      @Service:将类标识为业务层组件
      @Repository:将类标识为持久层组件
      注意:这几个标识组件都只能标识在类上,如果是接口,要标在接口的实现类上

    区别:
    通过查看源码我们得知,@Controller、@Service、@Repository这三个注解只是在@Component注解的基础上起了三个新的名字。
    对于Spring使用IOC容器管理这些组件来说没有区别。所以@Controller、@service、@Repository这三个注解只是给开发人员看的,让我们能够便于分辦组件的作用。

    注意:星然它们本质上一样,但是为了代码的可读性,为了程序结构严谨我们肯定不能随便胡乱标记。

    1. 创建组件
    @Controller
    public class UserController {
    }
    
    • 1
    • 2
    • 3
    @Repository
    public class UserDaoImpl implements UserDao {
    }
    
    • 1
    • 2
    • 3
    @Service
    public class UserServiceImpl implements UserService {
    }
    
    • 1
    • 2
    • 3
    1. 扫描组件
    
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           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">
    
        
        
        <context:component-scan base-package="com.bijing.spring" use-default-filters="true">
            
            
            
    
        context:component-scan>
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    1. 测试
        @Test
        public void testIOCByAnnotation() {
            ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-ioc-annotation.xml");
            UserController userController = ioc.getBean(UserController.class);
            System.out.println(userController);
            UserService userService = ioc.getBean(UserService.class);
            System.out.println(userService);
            UserDao userDao = ioc.getBean(UserDao.class);
            System.out.println(userDao);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    1. 组件所对应的bean的id
      通过注解+扫描所配置的bean的id,默认值为类的小驼峰,即类名首字母为小写
      可以在注解后面配置id
    @Controller("controller")
    public class UserController {
    }
    
    
    • 1
    • 2
    • 3
    • 4
    public class IOCByAnnotationTest {
    
        /**
         * @Component:将类标识为普通组件
         * @Controller:将类标识为控制层组件
         * @Service:将类标识为业务层组件
         * @Repository:将类标识为持久层组件 @
         * 通过注解+扫描所配置的bean的id,默认值为类的小驼峰,即类名首字母为小写
         */
    
        @Test
        public void testIOCByAnnotation() {
            ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-ioc-annotation.xml");
            UserController userController = ioc.getBean("controller", UserController.class);
            System.out.println(userController);
            UserService userService = ioc.getBean(UserService.class);
            System.out.println(userService);
            UserDao userDao = ioc.getBean(UserDao.class);
            System.out.println(userDao);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    关于Dao层、Service层和Controller层

    1. Dao层也叫数据持久层,是直接和数据库打交道的(写进数据库的数据相对是持久的)。Dao层的设计一般都是先设计接口,然后再设计该接口的实现类
    2. Service层也叫服务层,主要处理业务逻辑。Service层的设计也是先结构后实现
    3. Controller也叫业务层,主要处理业务流程。Controller层主要是与前台互交,把前台传进来的参数进行处理

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

    1. 场景模拟
      在这里插入图片描述

    2. @Autowired注解

    这个注解的功能就是为我们注入一个定义好的 bean

    @Controller()
    public class UserController {
        @Autowired
    //    @Qualifier("userServiceImpl")
        private UserService userService;
    
        public void saveUser() {
            userService.saveUser();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    @Repository()
    public class UserDaoImpl implements UserDao {
    
        @Override()
        public void saveUser() {
            System.out.println("保存成功");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    @Service
    public class UserServiceImpl implements UserService {
        @Autowired
       // @Qualifier("userDaoImpl")
        private UserDao userDao;
    
    
        public UserServiceImpl(UserDao userDao) {
            this.userDao = userDao;
        }
    
        public UserDao getUserDao() {
            return userDao;
        }
    
        public void setUserDao(UserDao userDao) {
            this.userDao = userDao;
        }
    
        @Override
        public void saveUser() {
            userDao.saveUser();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    1. @Autowired注解其他细节
    • @Autowired注解能够标识的位置
      • 标识在成员变量上,此时不需要设置成员变量的set方法
      • 标识在set方法上
      • 为当前成员变量赋值的有参构造器上
    • @Autowired注解的原理
      • 默认通过byType的方式,在IOC容器中通过类型匹配某个bean为属性赋值
      • 若有多个类型匹配的bean,此时会自动转换为byName的方式实现自动装配的效果, 即将要赋值的属性的属性名作为bean的id匹配某个bean的属性值
      • 若byType和byName的方式都无法实现自动装配,即IOC容器中有多个类型匹配的bean,且这些bean的id和要赋值的属性的属性名都不一致
      • 此时可以在要赋值的属性上添加一个@Qualifier注解,通过该注解的value属性值指定某个bean的id,用这个bean给属性赋值
    • @Qualifier注解
    @Controller()
    public class UserController {
        @Autowired
        @Qualifier("userServiceImpl")
        private UserService userService;
    
        public void saveUser() {
            userService.saveUser();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    //使用@Service注解默认id为userServiceImpl,这里的id和基于xml方式bean中的id一个意思.
    // @Service("userService")自定义id为userService,
    // 此时在UserController中就需要利用@Qualifier注解指定自动装配UserService的id为userService
    // @Qualifier("userService")
    @Service("userService")
    public class UserServiceImpl implements UserService {
        @Autowired
        @Qualifier("userDaoImpl")
        private UserDao userDao;
    
    
        public UserServiceImpl(UserDao userDao) {
            this.userDao = userDao;
        }
    
        public UserDao getUserDao() {
            return userDao;
        }
    
        public void setUserDao(UserDao userDao) {
            this.userDao = userDao;
        }
    
        @Override
        public void saveUser() {
            userDao.saveUser();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
        <context:component-scan base-package="com.bijing.spring">
            
            
            
    
        context:component-scan>
        
        
        <bean id="userServiceImpl" class="com.bijing.spring.service.impl.UserServiceImpl">bean>
        <bean id="userDaoImpl" class="com.bijing.spring.dao.impl.UserDaoImpl">bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 注意:若IOC容器中没有任何一个类型匹配的bean,此时抛出异常:NoSuchBeanDefinitionException
      • 在@Autowired注解中有个属性required,默认值为true,要求必须完成自动装配
      • 可以将required设置为false,此时能装配就装配,无法装配则使用属性默认值
    1. @Autowired工作流程
    package com.bijing.spring.test;
    
    import com.bijing.spring.controller.UserController;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    /**
     * @author 毕晶
     * @date 2022/11/12 20:45
     */
    public class IOCByAnnotationTest {
    
        /**
         * @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和要赋值的属性的属性名都不一致
         * d>此时可以在要赋值的属性上添加一个@Qualifier注解,通过该注解的value属性值指定某个bean的id,用这个bean给属性赋值
         * ##
         * 注意:若IOC容器中没有任何一个类型匹配的bean,此时抛出异常:NoSuchBeanDefinitionException
         * 在@Autowired注解中有个属性required,默认值为true,要求必须完成自动装配
         * 可以将required设置为false,此时能装配就装配,无法装配则使用属性默认值
         */
    
        @Test
        public void testIOCByAnnotation() {
            ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-ioc-annotation.xml");
            UserController userController = ioc.getBean(UserController.class);
            System.out.println(userController);
            userController.saveUser();
    //        UserService userService = ioc.getBean(UserService.class);
    //        System.out.println(userService);
    //        UserDao userDao = ioc.getBean(UserDao.class);
    //        System.out.println(userDao);
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
  • 相关阅读:
    第五天:java多线程(线程)
    ThreadLocal类
    deepstream·在python中安装pyds包
    金三银四来了-找工作有哪些平台/工具?
    Paket在Linux下使用问题
    记一次 .NET某账本软件 非托管泄露分析
    让EXCEL VBA支持鼠标滚轮,vb6 IDE鼠标滚轮插件原理
    【django-vue】封装logger 封装全局异常 封装response 数据库配置 用户表继承AbstractUser配置
    Sprinig Boot优雅实现接口幂等性
    iTOP-RK3568开发板Linux 修改kernel logo
  • 原文地址:https://blog.csdn.net/weixin_43903745/article/details/127824909