• Spring学习笔记9 SpringIOC注解式开发


    Spring学习笔记8 Bean的循环依赖问题_biubiubiu0706的博客-CSDN博客

    注解的存在主要是为了简化XML的配置.Spring6倡导全注解式开发

    回顾下

    注解怎么定义,注解中的属性怎么定义

    注解怎么使用

    通过反射机制怎么读取注解

    注解的自定义

    注解的使用

    通过反射机制怎么读取注解

    IOC之包扫描原理

    需求:给定一个包名,扫描所有类,只要有@Component注解,就创建该类对象,然后放到Map集合中

    Key为注解的value,Value为对象

    bean包下新建

    1. package com.example.client;
    2. import com.example.annotation.Component;
    3. import java.io.File;
    4. import java.net.URL;
    5. import java.util.Arrays;
    6. import java.util.HashMap;
    7. import java.util.Map;
    8. /**
    9. * 手写组件扫描
    10. * @author hrui
    11. * @date 2023/9/24 18:20
    12. */
    13. public class ComponentScan {
    14. public static void main(String[] args) throws Exception{
    15. //创建存放注解值的key和对象的容器
    16. Map<String,Object> beanMap=new HashMap<>();
    17. //目前只知道包名,扫描包下所有类,当类上有@Component注解时候,实例化该对象,放到Map
    18. String packageName="com.example.bean";
    19. //开始扫描
    20. //.这个正则表达式代表任意字符,这里的"."必须是一个普通的"."字符,不能是正则表达式中的"."
    21. String packagePath = packageName.replaceAll("\\.", "/");
    22. System.out.println(packagePath);
    23. URL url = ClassLoader.getSystemClassLoader().getResource(packagePath);
    24. String path = url.getPath();
    25. System.out.println(path);
    26. //获取绝对路径下所有文件
    27. File files=new File(path);
    28. File[] listFile = files.listFiles();
    29. Arrays.stream(listFile).forEach(f->{
    30. try {
    31. System.out.println(f.getName());
    32. System.out.println(f.getName().split("\\.")[0]);
    33. //拼接包名 获得类名
    34. String className=packageName+"."+f.getName().split("\\.")[0];
    35. System.out.println(className);
    36. //通过反射机制解析注解
    37. Class<?> clazz = Class.forName(className);
    38. //判断类上有没有@Component注解
    39. if(clazz.isAnnotationPresent(Component.class)){
    40. //获取注解
    41. Component annotation = clazz.getAnnotation(Component.class);
    42. String key=annotation.value();
    43. //有该注解就创建对象
    44. Object o = clazz.newInstance();
    45. beanMap.put(key, o);
    46. }
    47. } catch (Exception e) {
    48. e.printStackTrace();
    49. }
    50. });
    51. System.out.println(beanMap);
    52. }
    53. }

    上面就是包扫描的原理

    声明Bean的注解,常见的包括4个

    @Compoent   组件

    @Controller   控制器

    @Service   业务

    @Repository   DAO

    新建模块spring-010

    pom.xml

    
        
        
            org.springframework
            spring-context
            6.0.10
        
        
        
            junit
            junit
            4.13.2
            test
        
    
        
        
            org.apache.logging.log4j
            log4j-core
            2.19.0
        
        
            org.apache.logging.log4j
            log4j-slf4j-impl
            2.19.0
        
    

    引入日志文件,Spring默认用的log4j2   在resources目录下固定名称log4j2.xml日志文件即可

    
    
        
            
            
                
            
        
        
            
            
                
                
            
        
    
    

    上面4个注解的源码

    @Component

    看下@Controller   @Service   @Repository 

    说明@Component是老大  一样的效果

    其实作用是一样的,只为增加程序的可读性

    @Controller表示控制层    @Service表示业务层    @Repository表示持久层

    那我非不想这么写,都用@Component行不行,答案是:可以.你喜欢,你随意

    @Component   @Controller  @Service @Repository  这4个常用的Spring注解如何使用

    1.引入spring-context依赖--->里面的spring--aop依赖   这个已经引入

    2.在Spring配置文件中引入命名空间

    3.配置包扫描

    4.希望将对象交由Spring管理的类上加注解

    测试

    实际上,即使不取名,默认也有名,类名首字母小写

    将4个bean的注解里的vlaue去掉

    例如

    SpringIOC解决多个包扫描问题

    两种解决方案:

    1.在配置文件中指定多个包,用逗号隔开

    2.指定多个包的共同父包

    测试

    指定父包

    SpringIOC注解式开发之选择性实例化Bean

    例如某个包下有很多Bean,分别标注了@Component  @Controller  @Service  @Repository

    现在由于某种业务需要,允许@Controller注解的参与Bean管理,其他不实例化.

    第一种解决方案

    测试:只有A和C 创建对象了

    第二种解决方案

    负责注入的注解

    @Component  @Controller  @Service  @Repository 这四个注解是用来声明Bean的.

    声明后这些Bean交由Spring管理.

    如何给Bean的属性赋值,需要以下注解

    @Value 用于注入简单类型  可以用在属性上   set方法上   构造方法的形参上

    @Autowired  用于注入非简单类型  用于 构造方法上   方法上  形参上  属性上  注解上

    @Qualifier

    @Resource

    @Value注解是专门用来注入简单类型的,专门用来代替

    示例

    现在不需要set方法

    新建个配置文件

    测试

    再测一个

    另外 @Value还可以用在set方法上

    @Value还可以用在构造方法中

    再测

    注意:这样不行

    SpringIOC注解之@Autowired和 @Qualifier

    @Autowired注解可以用来注入非简单类型

    单独使用@Autowried注解.默认根据类型匹配----->byType

    如果要byName@Autowired和@Qualifier需要一起使用

    注意:@Autowired单独使用 都是byType

    需要byName要和@Qualifier一起使用

    另外建个包com.example2

    持久层接口

    持久层实现类

    业务层接口

    业务层实现类

    新建配置文件用以包扫描

    测试

    如果我接口下有多个实现类

    就报错了  原因 它找到两个

    需要@Autowired和@Qualifier联合使用 

    在Spring中,@Autowired 注解默认会使用"byType"方式进行自动装配,它会尝试按照被注入的类型(数据类型)去寻找匹配的依赖,然后将依赖注入到目标字段或方法参数中。如果存在多个匹配的依赖对象(同一类型的多个Bean),并且无法确定要注入哪一个时,它会引发一个异常。

    如果 "byType" 自动装配失败,Spring 不会自动尝试 "byName" 自动装配。如果有多个相同类型的 Bean,但您希望显式选择其中一个进行注入,您可以使用 @Qualifier 注解与 @Autowired 结合使用,以指定要注入的 Bean 的名称

    测试

    下面演示@Autowired的可以自动装配的位置,@Autowired单独使用时,有两个同类型的会报错,

    因此先把OrderDaoForMysql或者OrderDaoForOracle注释掉一个

    下面演示@Autowired的可以自动装配的位置

    @Autowired在构造方法上

    测试

    @Autowired在构造方法参数上

    测试

    有给属性赋值的构造方法,省略掉@Autowired行不行 (注意:这里要求构造方法必须只有一个,且该构造方法给属性赋值)

    测试

    @Autowired放在set方法上

    关于@Resource注解

    @Resource注解也可以完成非简单类型注入.它和@Autowired的区别是

    1.@Resource是JDK扩展包中的注解,是javaEE的.更具通用性

    2.@Autowired注解是Spring框架自己的

    3.@Resource注解默认byName,为指定名字使用属性名为name.通过name找不到会自动启用byType装配

    4.@Autowired默认byType,找不到的话不会自动用byName,需要通过@Qualifier来byName

    5.@Resource注解用在属性上,set方法上

    6.@Autowired注解用在属性上,set方法上,构造方法上,构造方法参数上

    @Resource注解属于JDK扩展包(如果是JDK8不需要额外引入依赖,高于JDK11或低于JDK8需要额外引入依赖)

    注意:Spring6开始不再支持JAVAEE,它支持JAKARTA9(需要引入依赖)

    如果用的Spring6的引依赖

    
        jakarta.annotation
        jakarta.annotation-api
        2.1.1
    

    如果用的Spring5 

    
        javax.annotation
        javax.annotation-api
        1.3.2
    

     

    这用的Spring6  引入依赖

    新建个包

    持久层接口

    持久层实现类

    业务层

    新建配置文件包扫描

    测试

    测试放在set方法上

    测试

    @Resource不能放在构造方法上

    @Resource(name="xxxxx")如果不指定名字  单写个@Resource会将属性名作为名字,如果找不到bean,会用byType

    如果

    SpringIOC全注解开发  将Spring配置文件干掉

  • 相关阅读:
    element Cascader 级联选择器动态通过接口获取二级三级数据
    【二进制部署k8s-1.29.4】五、kube-controller-manager安装配置
    vue-router 路由
    嵌入式笔试面试刷题(day12)
    创建react脚手架项目——demo(react18 + react-router 6)
    Stopwatch用法
    【华为OD机试|01】最远足迹(Java/C/Py/JS)
    GO安装以及配置(1)
    SpringBoot实现SSMP整合
    世界互联网大会|美创科技新一代 灾备一体化平台(DRCC v3.0)重磅亮相
  • 原文地址:https://blog.csdn.net/tiantiantbtb/article/details/133229542