当前位置: 首页 > news >正文

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

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

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

回顾下

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

注解怎么使用

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

注解的自定义

注解的使用

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

IOC之包扫描原理

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

Key为注解的value,Value为对象

bean包下新建

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<String,Object> beanMap=new HashMap<>();//目前只知道包名,扫描包下所有类,当类上有@Component注解时候,实例化该对象,放到MapString 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);}
}

上面就是包扫描的原理

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

@Compoent   组件

@Controller   控制器

@Service   业务

@Repository   DAO

新建模块spring-010

pom.xml

<dependencies><!--Spring依赖--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>6.0.10</version></dependency><!--junit单元测试--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope></dependency><!--Log4j2依赖--><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId><version>2.19.0</version></dependency><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-slf4j-impl</artifactId><version>2.19.0</version></dependency>
</dependencies>

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

<?xml version="1.0" encoding="UTF-8"?>
<configuration><loggers><!--level指定⽇志级别,从低到⾼的优先级:ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF--><root level="INFO"><appender-ref ref="spring6log"/></root></loggers><appenders><!--输出⽇志信息到控制台--><console name="spring6log" target="SYSTEM_OUT"><!--控制⽇志输出的格式--><PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss SSS} [%t] %-3level %logger{1024} - %msg%n"/></console></appenders>
</configuration>

上面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的引依赖

<dependency><groupId>jakarta.annotation</groupId><artifactId>jakarta.annotation-api</artifactId><version>2.1.1</version>
</dependency>

如果用的Spring5 

<dependency><groupId>javax.annotation</groupId><artifactId>javax.annotation-api</artifactId><version>1.3.2</version>
</dependency>

 

这用的Spring6  引入依赖

新建个包

持久层接口

持久层实现类

业务层

新建配置文件包扫描

测试

测试放在set方法上

测试

@Resource不能放在构造方法上

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

如果

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

http://www.lryc.cn/news/174667.html

相关文章:

  • 【新日标习题集】第13課 までのまとめ (discarded)
  • Java基础常考知识点(基础、集合、异常、JVM)
  • 虚拟机桥接模式下没有无线网卡选项
  • 设计模式笔记
  • c==ubuntu+vscode debug redis7源码
  • java字符串储存底层原理
  • c++获取当前时间的字符串
  • 【精品】通用Mapper 批量更新bug解决方案
  • 腾讯mini项目-【指标监控服务重构-会议记录】2023-07-06
  • 【React】函数式组件和类式组件的用法和逻辑
  • 题目 1061: 二级C语言-计负均正
  • 数位和(C++)
  • [牛客复盘] 牛客周赛round13 20230924
  • mybatsi-MyBatis的逆向工程
  • 转转闲鱼交易猫链接源码 支持二维码收款
  • Python爬虫基础(三):使用Selenium动态加载网页
  • Linux系统下安装Mysql
  • Jenkins学习笔记1
  • 注意力机制
  • JVM-Java字节码技术笔记
  • C++ 友元、重载、继承、多态
  • Spring Boot 日志文件
  • vulhub venom
  • 量化交易之One Piece篇 - linux - 定时任务(重启服务器、执行程序、验证)
  • Qt5开发及实例V2.0-第二十三章-Qt-多功能文档查看器实例
  • 爬虫笔记_
  • Spring设计模式,事务管理和代理模式的应用
  • 基于海康Ehome/ISUP接入到LiveNVR实现海康摄像头、录像机视频统一汇聚,做到物联网无插件直播回放和控制
  • Linux下git安装及使用
  • python读取图片