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

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

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

回顾下

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

注解怎么使用

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

注解的自定义

Spring学习笔记9 SpringIOC注解式开发_第1张图片

注解的使用

Spring学习笔记9 SpringIOC注解式开发_第2张图片

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

Spring学习笔记9 SpringIOC注解式开发_第3张图片

IOC之包扫描原理

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

Key为注解的value,Value为对象

bean包下新建

Spring学习笔记9 SpringIOC注解式开发_第4张图片

Spring学习笔记9 SpringIOC注解式开发_第5张图片

package com.example.client;

import com.example.annotation.Component;

import java.io.File;
import java.net.URL;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * 手写组件扫描
 * @author hrui
 * @date 2023/9/24 18:20
 */
public class ComponentScan {

    public static void main(String[] args) throws Exception{
        //创建存放注解值的key和对象的容器
        Map beanMap=new HashMap<>();
        //目前只知道包名,扫描包下所有类,当类上有@Component注解时候,实例化该对象,放到Map
        String packageName="com.example.bean";
        //开始扫描
        //.这个正则表达式代表任意字符,这里的"."必须是一个普通的"."字符,不能是正则表达式中的"."
        String packagePath = packageName.replaceAll("\\.", "/");
        System.out.println(packagePath);
        URL url = ClassLoader.getSystemClassLoader().getResource(packagePath);
        String path = url.getPath();
        System.out.println(path);
        //获取绝对路径下所有文件
        File files=new File(path);
        File[] listFile = files.listFiles();
        Arrays.stream(listFile).forEach(f->{

            try {
                System.out.println(f.getName());
                System.out.println(f.getName().split("\\.")[0]);
                //拼接包名 获得类名
                String className=packageName+"."+f.getName().split("\\.")[0];
                System.out.println(className);
                //通过反射机制解析注解
                Class clazz = Class.forName(className);
                //判断类上有没有@Component注解
                if(clazz.isAnnotationPresent(Component.class)){
                    //获取注解
                    Component annotation = clazz.getAnnotation(Component.class);
                    String key=annotation.value();
                    //有该注解就创建对象
                    Object o = clazz.newInstance();
                    beanMap.put(key, o);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        });

        System.out.println(beanMap);
    }
}

Spring学习笔记9 SpringIOC注解式开发_第6张图片

上面就是包扫描的原理

声明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

Spring学习笔记9 SpringIOC注解式开发_第7张图片

看下@Controller   @Service   @Repository 

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

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

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

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

Spring学习笔记9 SpringIOC注解式开发_第8张图片

Spring学习笔记9 SpringIOC注解式开发_第9张图片Spring学习笔记9 SpringIOC注解式开发_第10张图片

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

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

Spring学习笔记9 SpringIOC注解式开发_第11张图片

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

3.配置包扫描

Spring学习笔记9 SpringIOC注解式开发_第12张图片

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

Spring学习笔记9 SpringIOC注解式开发_第13张图片

Spring学习笔记9 SpringIOC注解式开发_第14张图片Spring学习笔记9 SpringIOC注解式开发_第15张图片Spring学习笔记9 SpringIOC注解式开发_第16张图片

测试

Spring学习笔记9 SpringIOC注解式开发_第17张图片

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

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

例如

Spring学习笔记9 SpringIOC注解式开发_第18张图片Spring学习笔记9 SpringIOC注解式开发_第19张图片

SpringIOC解决多个包扫描问题

两种解决方案:

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

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

Spring学习笔记9 SpringIOC注解式开发_第20张图片Spring学习笔记9 SpringIOC注解式开发_第21张图片

测试

Spring学习笔记9 SpringIOC注解式开发_第22张图片

指定父包

Spring学习笔记9 SpringIOC注解式开发_第23张图片

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

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

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

Spring学习笔记9 SpringIOC注解式开发_第24张图片

第一种解决方案

Spring学习笔记9 SpringIOC注解式开发_第25张图片

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

Spring学习笔记9 SpringIOC注解式开发_第26张图片

第二种解决方案

Spring学习笔记9 SpringIOC注解式开发_第27张图片

Spring学习笔记9 SpringIOC注解式开发_第28张图片

负责注入的注解

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

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

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

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

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

@Qualifier

@Resource

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

Spring学习笔记9 SpringIOC注解式开发_第29张图片

示例

现在不需要set方法

Spring学习笔记9 SpringIOC注解式开发_第30张图片

新建个配置文件

Spring学习笔记9 SpringIOC注解式开发_第31张图片

测试Spring学习笔记9 SpringIOC注解式开发_第32张图片

再测一个

Spring学习笔记9 SpringIOC注解式开发_第33张图片

Spring学习笔记9 SpringIOC注解式开发_第34张图片

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

Spring学习笔记9 SpringIOC注解式开发_第35张图片

Spring学习笔记9 SpringIOC注解式开发_第36张图片

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

Spring学习笔记9 SpringIOC注解式开发_第37张图片

Spring学习笔记9 SpringIOC注解式开发_第38张图片

再测

Spring学习笔记9 SpringIOC注解式开发_第39张图片

注意:这样不行

Spring学习笔记9 SpringIOC注解式开发_第40张图片

SpringIOC注解之@Autowired和 @Qualifier

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

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

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

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

需要byName要和@Qualifier一起使用

Spring学习笔记9 SpringIOC注解式开发_第41张图片

另外建个包com.example2

持久层接口

Spring学习笔记9 SpringIOC注解式开发_第42张图片

持久层实现类

Spring学习笔记9 SpringIOC注解式开发_第43张图片

业务层接口

Spring学习笔记9 SpringIOC注解式开发_第44张图片

业务层实现类

Spring学习笔记9 SpringIOC注解式开发_第45张图片

新建配置文件用以包扫描

Spring学习笔记9 SpringIOC注解式开发_第46张图片

测试

Spring学习笔记9 SpringIOC注解式开发_第47张图片

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

Spring学习笔记9 SpringIOC注解式开发_第48张图片

就报错了  原因 它找到两个

Spring学习笔记9 SpringIOC注解式开发_第49张图片

需要@Autowired和@Qualifier联合使用 

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

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

Spring学习笔记9 SpringIOC注解式开发_第50张图片

测试

Spring学习笔记9 SpringIOC注解式开发_第51张图片

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

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

Spring学习笔记9 SpringIOC注解式开发_第52张图片

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

@Autowired在构造方法上

Spring学习笔记9 SpringIOC注解式开发_第53张图片

测试

Spring学习笔记9 SpringIOC注解式开发_第54张图片

@Autowired在构造方法参数上

Spring学习笔记9 SpringIOC注解式开发_第55张图片

测试

Spring学习笔记9 SpringIOC注解式开发_第56张图片

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

Spring学习笔记9 SpringIOC注解式开发_第57张图片

测试

Spring学习笔记9 SpringIOC注解式开发_第58张图片

@Autowired放在set方法上

Spring学习笔记9 SpringIOC注解式开发_第59张图片

Spring学习笔记9 SpringIOC注解式开发_第60张图片

关于@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

 Spring学习笔记9 SpringIOC注解式开发_第61张图片

这用的Spring6  引入依赖

Spring学习笔记9 SpringIOC注解式开发_第62张图片

Spring学习笔记9 SpringIOC注解式开发_第63张图片

Spring学习笔记9 SpringIOC注解式开发_第64张图片

新建个包

持久层接口

Spring学习笔记9 SpringIOC注解式开发_第65张图片

持久层实现类

Spring学习笔记9 SpringIOC注解式开发_第66张图片

业务层

Spring学习笔记9 SpringIOC注解式开发_第67张图片

新建配置文件包扫描

Spring学习笔记9 SpringIOC注解式开发_第68张图片

测试

Spring学习笔记9 SpringIOC注解式开发_第69张图片

测试放在set方法上

Spring学习笔记9 SpringIOC注解式开发_第70张图片

测试

Spring学习笔记9 SpringIOC注解式开发_第71张图片

@Resource不能放在构造方法上

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

Spring学习笔记9 SpringIOC注解式开发_第72张图片Spring学习笔记9 SpringIOC注解式开发_第73张图片

如果

Spring学习笔记9 SpringIOC注解式开发_第74张图片Spring学习笔记9 SpringIOC注解式开发_第75张图片

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

Spring学习笔记9 SpringIOC注解式开发_第76张图片

Spring学习笔记9 SpringIOC注解式开发_第77张图片

你可能感兴趣的:(学习,笔记)