• (续)SSM整合之spring笔记(IOC 基于注解管理bean之注解和扫描,扫描组件,bean的id)(P087—P090)


    基于注解管理bean

     一. 实验一:标记与扫描(基于注解管理bean之注解和扫描)

    1 .注解与扫描的概念

    ①注解

    XML 配置文件一样,注解本身并不能执行,注解本身仅仅只是做一个标记,具体的功能是框架检测
    到注解标记的位置,然后针对这个位置按照注解标记的功能来执行具体操作。
    本质上:所有一切的操作都是 Java 代码来完成的, XML 和注解只是告诉框架中的 Java 代码如何执行。
    举例:元旦联欢会要布置教室,蓝色的地方贴上元旦快乐四个字,红色的地方贴上拉花,黄色的地方贴 上气球。

     

    班长做了所有标记,同学们来完成具体工作。墙上的标记相当于我们在代码中使用的注解,后面同学们 做的工作,相当于框架的具体操作。
    基于xml管理bean也是很多的   
    因为要管理bean, bean是一个对象  基于注解管理bean   注解是要加到当前对象所对应的类上的,
    如果让ioc管理第三方jar包里面提供的类  就没法用注解  因为这个不是我们自己写的  就好比druid
    是第三方jar包提供的   第三方放的都是calls文件  calls文件没法修改 加上注解  
    管理bean的二种方式: xml   注解

    ②扫描

    Spring 为了知道程序员在哪些地方标记了什么注解,就需要通过扫描的方式,来进行检测。然后根据注解进行后续操作。
    以后的实体类是不会交给ioc容器为管理的     所以不可能在每一个类上都加上注解  不可能每一类都交给ioc管理 所以不但要有注解还要扫描  
    演示  com.atguigu.spring

    2 .准备工作

    ① 新建spring_ioc_annotation 

    ②  导入依赖

    
        
        
            org.springframework
            spring-context
            5.3.1
        
        
        
            junit
            junit
            4.12
            test
        
    

    ③  创建三层架构 

    控制层 com.atguigu.spring.controller.UserController

    业务层 :com.atguigu.spring.service.UserService     接口

                   com.atguigu.spring.service.impl.UserServiceImpl   实现类 

    持久层:com.atguigu.spring.dao.UserDao    接口

                  com.atguigu.spring.dao.impl.UserDaoImpl    实现类

    代码如下 :

    控制层 com.atguigu.spring.controller.UserController

    1. package com.atguigu.spring.controller;
    2. public class UserController {
    3. }

    业务层 :com.atguigu.spring.service.UserService     接口

                   com.atguigu.spring.service.impl.UserServiceImpl   实现类 

    1. package com.atguigu.spring.service;
    2. public interface UserService {
    3. }
    1. package com.atguigu.spring.service.impl;
    2. import com.atguigu.spring.service.UserService;
    3. public class UserServiceImpl implements UserService {
    4. }

    持久层:com.atguigu.spring.dao.UserDao    接口

                  com.atguigu.spring.dao.impl.UserDaoImpl    实现类

    1. package com.atguigu.spring.dao;
    2. public interface UserDao {
    3. }
    1. package com.atguigu.spring.dao.impl;
    2. import com.atguigu.spring.dao.UserDao;
    3. public class UserDaoImpl implements UserDao {
    4. }

    ④   创建Spring配置文件 spring-ioc-annotation.xml

    ⑤  测试类   IOCByAnnotationTest

    1. package com.atguigu.spring.test;
    2. import org.junit.Test;
    3. public class IOCByAnnotationTest {
    4. @Test
    5. public void test(){
    6. }
    7. }

     

    3 .现在我们要做的事情

    现在要做的事情就是通过注解来管理bean  那我们有哪些注解呢?

    我们现在要把一个类交给IOC来管理  我们要用到以下四个注解

    ① 标识组件的常用注解

    @Component :将类标识为普通组件
    组件:每一个bean都是IOC容器的组件   所以将类标识为普通组件就是加上这个注解并扫描之后,就可以把当前加上这个注解的类做为一个bean 被IOC容器管理 
    @Controller :将类标识为控制层组件
    @Service :将类标 识为业务层组件
    @Repository :将类标识为持久层组件
    问:以上四个注解有什么关系和区别?
    通过查看源码我们得知, @Controller @Service @Repository 这三个注解只是在 @Component 注解
    的基础上起了三个新的名字。
    对于 Spring 使用 IOC 容器管理这些组件来说没有区别。所以 @Controller @Service @Repository
    三个注解只是给开发人员看的,让我们能够便于分辨组件的作用。
    注意:虽然它们本质上一样,但是为了代码的可读性,为了程序结构严谨我们肯定不能随便胡乱标记。

    ②  接下来我们要把注解标记在我们刚才创建的三层架构上

    代码如下:

    控制层组件
    1. package com.atguigu.spring.controller;
    2. import org.springframework.stereotype.Controller;
    3. @Controller
    4. public class UserController {
    5. }
    业务层组件 UserServiceImpl
    1. package com.atguigu.spring.service.impl;
    2. import com.atguigu.spring.service.UserService;
    3. import org.springframework.stereotype.Service;
    4. @Service
    5. public class UserServiceImpl implements UserService {
    6. }
    持久层组件 UserDaoImpl
    1. package com.atguigu.spring.dao.impl;
    2. import com.atguigu.spring.dao.UserDao;
    3. import org.springframework.stereotype.Repository;
    4. @Repository
    5. public class UserDaoImpl implements UserDao {
    6. }

    注意:注解不能加到接口   一定要加到实现类上  

    因为加上注解的作用是:  加上注解的类在IOC容器中配置了一个当前类型的bean  一个bean的类型不能够是一个接口类型  

    ③  接下去 我们要在配置文件spring-ioc-annotation.xml里面进行扫描

    为什么要扫描:

    在类上加上注解 要想让spring知道  得要扫描  要让spring知道哪些类加上了注解  加了什么注解  

    因为一层一层的包 就是一层一层的目录  所以我们主要扫描包就可以

    1. <context:component-scan base-package="com.atguigu.spring">context:component-scan>

    ④  接下来我们来进行测试一下

    在理解一下 注解+扫描的意思:

    它可以将我们扫描的包下 加上注解的这些类做为组件进行管理 

    做为组件进行管理:在IOC容器中就有了 当前加上这个注解 的这个类 所对应的bean对象

    测试:

    1. import org.springframework.context.ApplicationContext;
    2. import org.springframework.context.support.ClassPathXmlApplicationContext;
    3. public class IOCByAnnotationTest {
    4. /* @Component:将类标识为普通组件
    5. * @Controller:将类标识为控制层组件
    6. * @Service:将类标识为业务层组件
    7. * @Repository:将类标识为持久层组件*/
    8. @Test
    9. public void test(){
    10. ApplicationContext ioc =new ClassPathXmlApplicationContext("spring-ioc-annotation.xml");
    11. UserController userController = ioc.getBean(UserController.class);
    12. System.out.println(userController);
    13. UserService userService = ioc.getBean(UserService.class);
    14. System.out.println(userService);
    15. UserDao userDao = ioc.getBean(UserDao.class);
    16. System.out.println(userDao);
    17. }
    18. }

      二. 标记与扫描(基于注解管理bean之扫描组件)

    问题:

    以后在ssm整合的时候  spring 和springmvc 是放在一块使用的  而springmvc要扫描的是我们的控制层,spring要扫描的是除控制层以外的所有组件    这个时候应该怎么办?
    如果springmvc 把控制层给扫描了  spring也把控制层扫描了  这个时候一个组件就被扫描多次  

    我们现在要做的是 springmvc 扫描控制层 然后spring把其他的层给扫描了 

    就要用到排除扫描标签 具体如下

    1 .排除扫描

     
         

    第一种  annotation:根据注解的类型进行排除,expression需要设置排除的注解的全类名(用得多)

    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">
    7. <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    8. context:component-scan>
    9. beans>

    测试:

    1. @Test
    2. public void test(){
    3. ApplicationContext ioc =new ClassPathXmlApplicationContext("spring-ioc-annotation.xml");
    4. UserController userController = ioc.getBean(UserController.class);
    5. System.out.println(userController);
    6. UserService userService = ioc.getBean(UserService.class);
    7. System.out.println(userService);
    8. UserDao userDao = ioc.getBean(UserDao.class);
    9. System.out.println(userDao);
    10. }
    11. }

     

    虽然在控制层加了 但是因为排除了 所以并没有扫描到   但是不影响对其他层的扫描 如下 测试

    1. @Test
    2. public void test(){
    3. ApplicationContext ioc =new ClassPathXmlApplicationContext("spring-ioc-annotation.xml");
    4. /* UserController userController = ioc.getBean(UserController.class);
    5. System.out.println(userController);*/
    6. UserService userService = ioc.getBean(UserService.class);
    7. System.out.println(userService);
    8. UserDao userDao = ioc.getBean(UserDao.class);
    9. System.out.println(userDao);
    10. }

     

    全类名的复制方法;

    要把控制层的扫描给排除掉  所以我们找到控制层 找到注解 点击右键  把全类名放过来  这个时候就不扫描控制层了 

      第二种 :assignable:根据类的类型进行排除,expression需要设置排除的类的全类名(用得少)

    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">
    7. <context:exclude-filter type="assignable" expression="com.atguigu.spring.controller.UserController"/>
    8. context:component-scan>
    9. beans>

    测试:

    1. public class IOCByAnnotationTest {
    2. /* @Component:将类标识为普通组件
    3. * @Controller:将类标识为控制层组件
    4. * @Service:将类标识为业务层组件
    5. * @Repository:将类标识为持久层组件*/
    6. @Test
    7. public void test(){
    8. ApplicationContext ioc =new ClassPathXmlApplicationContext("spring-ioc-annotation.xml");
    9. UserController userController = ioc.getBean(UserController.class);
    10. System.out.println(userController);
    11. UserService userService = ioc.getBean(UserService.class);
    12. System.out.println(userService);
    13. UserDao userDao = ioc.getBean(UserDao.class);
    14. System.out.println(userDao);
    15. }
    16. }

    全类名的复制方法

    我们找到控制层 找到UserController类 点击右键  把全类名放过来  这个时候在扫描包的时候就会把UserController类给排除 

     注意:以后用得比较多的是根据注解的方式排除 因为以后要用到这个标签

    二种方法整合一起并解释:

    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">
    7. <context:exclude-filter type="assignable" expression="com.atguigu.spring.controller.UserController"/>
    8. context:component-scan>
    9. beans>

    总结:

    2 .包含扫描   只扫描

    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" >
    7. <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    8. context:component-scan>
    9. beans>

    测试:

    1. public class IOCByAnnotationTest {
    2. /* @Component:将类标识为普通组件
    3. * @Controller:将类标识为控制层组件
    4. * @Service:将类标识为业务层组件
    5. * @Repository:将类标识为持久层组件*/
    6. @Test
    7. public void test(){
    8. ApplicationContext ioc =new ClassPathXmlApplicationContext("spring-ioc-annotation.xml");
    9. UserController userController = ioc.getBean(UserController.class);
    10. System.out.println(userController);
    11. UserService userService = ioc.getBean(UserService.class);
    12. System.out.println(userService);
    13. UserDao userDao = ioc.getBean(UserDao.class);
    14. System.out.println(userDao);
    15. }
    16. }
     
         

    测试结果发现都可以扫描到

    修正如下:

    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" use-default-filters="false">
    7. <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    8. context:component-scan>
    9. beans>

     测试:

    1. public class IOCByAnnotationTest {
    2. /* @Component:将类标识为普通组件
    3. * @Controller:将类标识为控制层组件
    4. * @Service:将类标识为业务层组件
    5. * @Repository:将类标识为持久层组件*/
    6. @Test
    7. public void test(){
    8. ApplicationContext ioc =new ClassPathXmlApplicationContext("spring-ioc-annotation.xml");
    9. UserController userController = ioc.getBean(UserController.class);
    10. System.out.println(userController);
    11. UserService userService = ioc.getBean(UserService.class);
    12. System.out.println(userService);
    13. UserDao userDao = ioc.getBean(UserDao.class);
    14. System.out.println(userDao);
    15. }
    16. }

    总结:

    context:include-filter:包含扫描
    注意:需要在context:component-scan标签中设置use-default-filters="false"
    use-default-filters="true"(默认),所设置的包下所有的类都需要扫描,此时可以使用排除扫描
    use-default-filters="false",所设置的包下所有的类都不需要扫描,此时可以使用包含扫描

     二种方法全部总结:

     我们以后排除扫描用得比较多  包含扫描用得比较少 因为麻烦

    平常用的话只要下如下就可以

    1. <context:component-scan base-package="com.atguigu.spring">context:component-scan>
    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. beans>

    . 标记与扫描(基于注解管理bean之bean的id)

    在我们使用 XML 方式管理 bean 的时候,每个 bean 都有一个唯一标识,便于在其他地方引用。现在使用 注解后,每个组件仍然应该有一个唯一标识。
    默认情况
    类名首字母小写就是 bean id 。例如: UserController 类对应的 bean id 就是 userController
    自定义 bean id
    可通过标识组件的注解的 value 属性设置自定义的 bean id
    @Service("userService")// 默认为 userServiceImpl public class UserServiceImpl implements
    UserService {}

    复习:

    注解所标识的类交给IOC管理:

    注解标识的类经过 扫描之后在IOC容器中 自动去配置一个相对应的bean 

    新知识:

    问题:我们知道bean 都是有id的  通过注解+扫描的id是啥呢?

    答案:通过注解+扫描所配置的bean的id,默认值为类的小驼峰,即类名的首字母为小写的结果

    验证:

    IOCByAnnotationTest

    1. public class IOCByAnnotationTest {
    2. /* @Component:将类标识为普通组件
    3. * @Controller:将类标识为控制层组件
    4. * @Service:将类标识为业务层组件
    5. * @Repository:将类标识为持久层组件*/
    6. @Test
    7. public void test(){
    8. ApplicationContext ioc =new ClassPathXmlApplicationContext("spring-ioc-annotation.xml");
    9. UserController userController = ioc.getBean("userController",UserController.class);
    10. System.out.println(userController);
    11. UserService userService = ioc.getBean("userServiceImpl",UserService.class);
    12. System.out.println(userService);
    13. UserDao userDao = ioc.getBean("userDaoImpl",UserDao.class);
    14. System.out.println(userDao);
    15. }
    16. }
     
         

     自定义bean的id 

    可以通过标识组件的注解的value属性值设置bean的自定义的id

    UserController

    1. package com.atguigu.spring.controller;
    2. import org.springframework.stereotype.Controller;
    3. @Controller("controller")
    4. public class UserController {
    5. }

    1. public class IOCByAnnotationTest {
    2. /* @Component:将类标识为普通组件
    3. * @Controller:将类标识为控制层组件
    4. * @Service:将类标识为业务层组件
    5. * @Repository:将类标识为持久层组件*/
    6. @Test
    7. public void test(){
    8. ApplicationContext ioc =new ClassPathXmlApplicationContext("spring-ioc-annotation.xml");
    9. UserController userController = ioc.getBean("controller",UserController.class);
    10. System.out.println(userController);
    11. UserService userService = ioc.getBean("userServiceImpl",UserService.class);
    12. System.out.println(userService);
    13. UserDao userDao = ioc.getBean("userDaoImpl",UserDao.class);
    14. System.out.println(userDao);
    15. }
    16. }

     

     

    springmvc文件上传解析器  就是根据id来获取的 

    其他的地方一般用到的都是根据类型来获取 

     

     

     

     

     

     
      
     
      

                     

     
      
     
      

     

     
     

  • 相关阅读:
    网络知识(入门)
    国外网站国内镜像
    系统太多,多账号互通如何实现?
    JAVA毕设项目Web企业客户管理系统(Vue+Mybatis+Maven+Mysql+sprnig+SpringMVC)
    设计模式-用代理模式(Proxy Pattern)来拯救你的代码:打造可靠的程序设计
    三、Nginx核心配置文件
    Linux系统中安装Elasticsearch并实现开机自动启动
    对批量文件重命名
    【软件逆向-分析流程】关键代码定位、加密算法识别
    Linux CentOS7 vim多窗口编辑
  • 原文地址:https://blog.csdn.net/m0_59281987/article/details/127659119