商城网站建设费用,网上商城网站开发与建立的意义,文创产品设计书籍,公司网站备案需要哪些资料Spring学习笔记8 Bean的循环依赖问题_biubiubiu0706的博客-CSDN博客
注解的存在主要是为了简化XML的配置.Spring6倡导全注解式开发
回顾下
注解怎么定义,注解中的属性怎么定义
注解怎么使用
通过反射机制怎么读取注解 注解的自定义 注解的使用 通过反射机制怎么读取注解 I…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和对象的容器MapString,Object beanMapnew HashMap();//目前只知道包名,扫描包下所有类,当类上有Component注解时候,实例化该对象,放到MapString packageNamecom.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 filesnew 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 classNamepackageName.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 keyannotation.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依赖--dependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdversion6.0.10/version/dependency!--junit单元测试--dependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion4.13.2/versionscopetest/scope/dependency!--Log4j2依赖--dependencygroupIdorg.apache.logging.log4j/groupIdartifactIdlog4j-core/artifactIdversion2.19.0/version/dependencydependencygroupIdorg.apache.logging.log4j/groupIdartifactIdlog4j-slf4j-impl/artifactIdversion2.19.0/version/dependency
/dependencies 引入日志文件,Spring默认用的log4j2 在resources目录下固定名称log4j2.xml日志文件即可 ?xml version1.0 encodingUTF-8?
configurationloggers!--level指定⽇志级别从低到⾼的优先级ALL TRACE DEBUG INFO WARN ERROR FATAL OFF--root levelINFOappender-ref refspring6log//root/loggersappenders!--输出⽇志信息到控制台--console namespring6log targetSYSTEM_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
如果要byNameAutowired和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的引依赖 dependencygroupIdjakarta.annotation/groupIdartifactIdjakarta.annotation-api/artifactIdversion2.1.1/version
/dependency 如果用的Spring5 dependencygroupIdjavax.annotation/groupIdartifactIdjavax.annotation-api/artifactIdversion1.3.2/version
/dependency 这用的Spring6 引入依赖 新建个包
持久层接口 持久层实现类 业务层 新建配置文件包扫描 测试 测试放在set方法上 测试 Resource不能放在构造方法上 Resource(namexxxxx)如果不指定名字 单写个Resource会将属性名作为名字,如果找不到bean,会用byType 如果 SpringIOC全注解开发 将Spring配置文件干掉