Spring学习笔记注解式开发(3)
Spring学习笔记(3)
- 一、Bean的注解式开发
- 1.1、注解开发的基本和@Component
- 1.2 注解式开发
- 8.3、@Component的三个衍生注解
- 二、Bean依赖注入注解开发
- 2.1、依赖注入相关注解
- 2.2、@Autowired扩展
- 三、非自定义Bean注解开发
- 四、Bean配置类的注解开发
- 五、Spring注解的解析原理
- 六、Spring注解式开发第三方框架
一、Bean的注解式开发
1.1、注解开发的基本和@Component
Spring除了xml配置文件进行配置之外,还可以使用注解方式进行配置,注解方式慢慢成为xml配置的替代方案。我们有了xml开发的经验,学习注解开发就方便了许多,注解开发更加快捷方便。
- Spring提供的注解有三个版本:
- 2.0时代,Spring开始出现注解
- 2.5时代,Spring的Bean配置可以使用注解完成
- 3.0时代,Spring其他配置也可以使用注解完成,我们进入全注解时代
基本Bean注解,主要是使用注解的方式替代原有xml的<bean>
标签及其标签属性的配置
<bean id="" name="" class="" scope="" lazy-init="" init-method="" destroy-method=""abstract="" autowire="" factory-bean="" factory-method=""></bean>
使用@Component注解替代<bean>
标签
xml配置 | 注解 | 描述 |
---|---|---|
<bean id="" class=""> | @Component | 被该注解表示的类,会在指定扫描范围内被Spring加载并实例化 |
//<bean id="userDao" class="com.Smulll.Dao.Impl.UserDaoImpl"></bean>
@Component("userDao")
public class UserDaoImpl implements UserDao{@Overridepublic void show() {}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!--注解组件扫描--><!--扫描指定的基本包及其子包下的类,识别使用@Component注解--><context:component-scan base-package="com.huanglei"/>
</beans>
public class test1 {@Testpublic void ComponentTest(){ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("beans.xml");Object bean = classPathXmlApplicationContext.getBean("userDao");System.out.println(bean);}
}
1.2 注解式开发
如果@Component不设置name属性,那会回自动将首字母小写的类名转化成name,在访问的时候就用其首字母小写的类名进行访问
- 相关属性用注解开发替代的标签
xml配置 | 注解 | 描述 |
---|---|---|
<bean scope=""> | @Scope | 在类上或使用了@Bean标注的方法上,标注Bean的作用范围,取值为singleton或prototype |
<bean lazy-init=""> | @Lazy | 在类上或使用了@Bean标注的方法上,标注Bean是否延迟加载,取值为true和false |
<bean init-method=""> | @PostConstruct | 在方法上使用,标注Bean的实例化后执行的方法 |
<bean destroy-method=""> | @PreDestroy | 在方法上使用,标注Bean的销毁前执行方法 |
8.3、@Component的三个衍生注解
由于JavaEE开发是分层的,为了每层Bean标识的注解语义化更加明确,可以乱写,但是为了让注解语义化明确,建议按照标准书写
- @Component又衍生出如下三个注解:
@Component衍生注解 | 描述 |
---|---|
@Repository | 在Dao层类上使用 |
@Service | 在Service层类上使用 |
@Controller | 在Web层类上使用 |
//service层
@Service("userService")
public class UserServiceImpl implements UserService{}
//dao层
@Repository("userDao")
public class UserDaoImpl implements UserDao{}
//web层
@Controller("userService")
public class UserController{}
二、Bean依赖注入注解开发
2.1、依赖注入相关注解
Bean依赖注入的注解,主要是使用注解的方式替代xml的标签完成属性的注入操作
<bean id=" "class=""><property name="" value=""/><property name="" ref=""/>
</bean>
- Spring主要提供如下注解,用于在Bean内部进行属性注入的:
属性注入注解 | 描述 |
---|---|
@Value | 使用在字段或方法上,用于注入普通数据 |
@Autowired | 使用在字段或方法上,用于根据类型(byType)注入引用数据 |
@Qualifier | 使用在字段或方法上,结合@Autowired,根据名称注入 |
@Resource | 使用在字段或方法上,根据类型或名称进行注入 |
- @Value一般会引用Spring容器里面的一些值,根据key进行获取
- @Autowired根据类型进行注入,如果同一类型的Bean有多个,尝试根据书写的名字进行二次匹配,如果匹配不成功则会报错
- 配合使用@Qualifier注解,可以在同一类型的多个Bean中根据名称注入相应的Bean
- @Resource不指定名称参数时,根据类型注入,指定名称则根据名称注入
@Service("userService")
public class UserServiceImpl implements UserService{@Value("zhangsan")private String username;//@Autowired,如果同一类型的Bean有多个,尝试根据名字进行二次匹配,如果匹配不成功则会报错//@Qualifier("userDao2"),配合使用@Autowired注解,可以在同一类型的多个Bean中根据名称注入相应的Bean@Resource private UserDao userDao;@Overridepublic void show() {System.out.println(username);System.out.println(userDao);}
}
2.2、@Autowired扩展
@Autowired使用该注解时,所查看的是参数的类型,跟方法的名称无关
@Service("userService")
public class UserServiceImpl implements UserService{@Autowired public void xxx(UserDao userDao) {System.out.println("xxx:"+userDao);}
}
该注解同样可以获取一个集合,可以将同一类型的多个Bean打印出来
@Service("userService")
public class UserServiceImpl implements UserService{@Autowired public void yyy(List<UserDao> userDaoList) {System.out.println("yyy:"+userDaoList);}
}
三、非自定义Bean注解开发
非自定义Bean不能像自定义Bean一样使用@Component进行管理,非自定义Bean要通过工厂的方式进行实例化,使用@Bean标注方法
即可,@Bean的属性为beanName
,如不指定为当前工厂方法名称
//将方法返回值Bean实例以@Bean注解指定的名称存储到spring容器中
@Bean ("datasource")
public DataSource dataSource (){DruidDataSource dataSource = new DruidDataSource();dataSource.setDriverClassName("com.mysql.jdbc.Driver");dataSource.setUrl("jdbc:mysql://localhost:3306/itheima");dataSource.setUsername("root");dataSource.setPassword("123456");return dataSource;
}
@Bean标注后面不加name值,则将类名赋值为name属性值
- 在参数中注入
@Component
public class otherBean {@Bean("dataSource")public DataSource dataSource(@Value("${jdbc.driver}") String driver@Qualifier("userDao") UserDao UserDao//不需要写@Autowired){DruidDataSource dataSource = new DruidDataSource();dataSource.setDriverClassName(driver);dataSource.setUrl("jdbc:mysql://localhost:3306/mybatis");dataSource.setUsername("root");dataSource.setPassword("123456");return dataSource;}
}
四、Bean配置类的注解开发
@component --> <bean>
@Configuration --> 表示上面配置的文件
下面是其他的标签注解开发展示:
<!--扫描Spring管理的包--><context:component-scan base-package="com.huanglei"/><!--加载properties文件---><context:properties-placeholder location="classpath:jdbc.properties"/><!--引入其他的xml文件--><import resource="classpath:beans.xml"/>
在用注解式开发的时候需要在配置类上加 @Configuration
作用:
- 表明这是一个配置类
- 使其就具备@Component的功能
xml配置 | 注解 | 描述 |
---|---|---|
<context:component-scan base-package="com.huanglei"/> | @ComponentScan | 组件扫描配置 |
<context:property-placeholder location="classpath:jdbc.properties"/> | @PropertySource | 获取到properties文件里的信息 |
<import resource="classpath:beans.xml"> | @Import | 导入其他的xml配置文件 |
base-package的配置方法:
- 可以配置一个或者多个包:扫描的为该包及其子包下使用注解的类
- 不配置包名:扫描当前@componentScan注解配置类所在包及其子包下的类
@Component
@Configuration
@ComponentScan(backages={"com.huanglei","com.itheima"})
@PropertySource({"classpath:jdbc.properties"})
//<import resource=""/>
@Import(otherBean.class)
public class SpringConfig {}
其他的注解式开发:
@Primary
这个是来调节同类型Bean优先顺序的,就是说在利用ByTybe调用bean对象的时候有多个对象,如果没有@primary
,那么就按照之前的调用规则进行调用,如果存在@Primary那么就有限调用这个Bean对象
@Repository("userDao")
public class UserDaoImpl implements UserDao{}
@Repository("userDao2")
@Primary
public class UserDaoImpl2 implements UserDao{}
@Bean("dataSource")
public DataSource dataSource(){}@Bean("dataSource2")
@Primary //如果没添加这个,那么在调用的时候,就会按照名字调用上面那个Bean对象
public DataSource dataSource2(){}
扩展:@Profile注解的作用同于xml配置时学习profile属性,是进行环境切换使用的
<beans profile="test">
注解@Profile标注在类或方法上
,标注当前产生的Bean从属于哪个环境,只有激活了当前环境
,被标注的Bean才能被注册到Spring容器里,不指定环境的Bean
,任何环境下都能注册到Spring容器里
@Repository("userDao")
@Profile("test") //表面实在test环境下面
public class UserDaoImpl implements UserDao{}
@Repository("userDao2")
public class UserDaoImpl2 implements UserDao{}
- 可以使用以下两种方式指定被激活的环境:
- 使用命令行动态参数,虚拟机参数位置加载
-Dspring.profiles.active=test
- 使用代码的方式设置环境白能量
System.setProperty("profiles.active","test");
- 使用命令行动态参数,虚拟机参数位置加载
@Test
public void test2(){System.setProperty("spring.profiles.active","test");AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);Object userDao = annotationConfigApplicationContext.getBean("userDao");System.out.println(userDao);
}
五、Spring注解的解析原理
结论:只要将Bean对应的BeanDefinition注册到beanDefinitionMap中,就可以经历整个SpringBean的生命周期,最终实例化进入单例池中
使用@Component等注解配置完毕后,要配置组件扫描才能使注解生效
六、Spring注解式开发第三方框架
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property><property name="url" value="jdbc:mysql://localhost:3306/mybatis2"></property><property name="username" value="root"></property><property name="password" value="123456"></property>
</bean>
<!--配置SqlSessionFactoryBean,作用将SqlSessionFactory存储到spring容器-->
<bean class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource"></property>
</bean>
<!--MapperScannerConfigurer,作用扫描指定的包,产生Mapper对象存储到Spring容器-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="com.Smulll.mapper"></property>
</bean>
使用注解方式:
注解方式,Spring整合MyBatis的原理,关键在于**@MapperScan**,@MapperScan不是Spring提供的注解,是MyBatis为了整合Spring,在整合包org.mybatis.spring.annotation中提供的注解,源码如下:
package com.huanglei.listener;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.w3c.dom.css.CSSPrimitiveValue;import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;public class ContextLoaderListener implements ServletContextListener {private String CONTEXT_LOCATION = "configLocation";@Overridepublic void contextInitialized(ServletContextEvent sec) {//获取到全局变量configLocationServletContext servletContext = sec.getServletContext();String contextLocation = servletContext.getInitParameter(CONTEXT_LOCATION);contextLocation = contextLocation.substring("classpath:".length());//首先创建Spring容器ApplicationContext applicationContext = new ClassPathXmlApplicationContext(contextLocation);//将Spring容器放到ServletContext域当中servletContext.setAttribute("applicationContext",applicationContext);}@Overridepublic void contextDestroyed(ServletContextEvent servletContextEvent) {}
}
重点关注一下@lmport({MapperScannerRegistrar.class),当@MapperScan被扫描加载时,会解析@Import注解,从而加载指定的类,此处就是加载了MapperScannerRegistrar
相关文章:

Spring学习笔记注解式开发(3)
Spring学习笔记(3) 一、Bean的注解式开发1.1、注解开发的基本和Component1.2 注解式开发8.3、Component的三个衍生注解 二、Bean依赖注入注解开发2.1、依赖注入相关注解2.2、Autowired扩展 三、非自定义Bean注解开发四、Bean配置类的注解开发五、Spring注…...

vue3后台管理框架之技术栈
vue3全家桶技术 基础构建: vue3vite4TypeScript 代码格式 : eslintprettystylelint git生命周期钩子: husky css预处理器: sass ui库: element-plus 模拟数据: mock 网络请求: axios 路由: vue…...

7、Linux驱动开发:设备-自动创建设备节点
目录 🍅点击这里查看所有博文 随着自己工作的进行,接触到的技术栈也越来越多。给我一个很直观的感受就是,某一项技术/经验在刚开始接触的时候都记得很清楚。往往过了几个月都会忘记的差不多了,只有经常会用到的东西才有可能真正记…...

用Python解析HTML页面
用Python解析HTML页面 文章目录 用Python解析HTML页面HTML 页面的结构XPath 解析CSS 选择器解析简单的总结 在前面的课程中,我们讲到了使用 request三方库获取网络资源,还介绍了一些前端的基础知识。接下来,我们继续探索如何解析 HTML 代码&…...

官方认证:研发效能(DevOps)工程师职业技术认证
培养端到端的研发效能人才 为贯彻落实《关于深化人才发展体制机制改革的意见》,推动实施人才强国战略,促进专业技术人员提升职业素养、补充新知识新技能,实现人力资源深度开发,推动经济社会全面发展,根据《中华人民共…...

搭建GPFS双机集群
1.环境说明: 系统主机名IP地址内存添加共享磁盘大小Centos7.9gpfs1192.168.10.1012G20GCentos7.9gpfs2192.168.10.1022G20G 2.环境配置: 配置网路IP地址: 修改网卡会话: nmcli connection modify ipv4.method manual ipv4.addre…...

【试题032】C语言关系运算符例题
1.题目:设int a2,b4,c5;,则表达式ab!c>b>a的值为? 2.代码分析: //设int a2,b4,c5;,则表达式ab!c>b>a的值为?int a 2, b 4, c 5;printf("%d\n", (a b ! c > b > a));//分析ÿ…...

系列四、FileReader和FileWriter
一、概述 FileReader 和 FileWriter 是字符流,按照字符来操作IO。 1.1、继承体系 二、FileReader常用方法 new FileReader(File/String)# 每次读取单个字符就返回,如果读取到文件末尾返回-1 read()# 批量读取多个字符到数组,返回读取的字节…...

【C++面向对象】2.构造函数、析构函数
文章目录 【 1. 构造函数 】1.1 带参构造函数--传入数据1.2 无参构造函数--不传入数据1.3 实例1.4 拷贝构造函数 【 2. 析构函数 】 【 1. 构造函数 】 类的构造函数是类的一种特殊的成员函数,它会 在每次创建类的新对象时执行。 构造函数的名称与类的名称是完全相同…...

uniapp:使用subNVue原生子窗体在map上层添加自定义组件
我们想要在地图上层添加自定义组件,比如一个数据提示框,点一下会展开,再点一下收起,在h5段显示正常,但是到app端真机测试发现组件显示不出来,这是因为map是内置原生组件,层级最高,自…...

Flutter开发GridView控件详解
GridView跟ListView很类似,Listview主要以列表形式显示数据,GridView则是以网格形式显示数据,掌握ListView使用方法后,会很轻松的掌握GridView的使用方法。 在某种界面设计中,如果需要很多个类似的控件整齐的排列&…...

Vue3.0里为什么要用 Proxy API 替代 defineProperty API ?
一、Object.defineProperty 定义:Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象 为什么能实现响应式 通过defineProperty 两个属性,get及set get 属性的 getter 函…...

pytest利用request fixture实现个性化测试需求详解
这篇文章主要为大家详细介绍了pytest如何利用request fixture实现个性化测试需求,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起了解一下− 前言 在深入理解 pytest-repeat 插件的工作原理这篇文章中,我们看到pytest_repeat源码中有这样一段 import pyt…...
算法练习16——O(1) 时间插入、删除和获取随机元素
LeetCode 380 O(1) 时间插入、删除和获取随机元素 实现RandomizedSet 类: RandomizedSet() 初始化 RandomizedSet 对象 bool insert(int val) 当元素 val 不存在时,向集合中插入该项,并返回 true ;否则,返回 false 。 …...

实时数据更新与Apollo:探索GraphQL订阅
前言 「作者主页」:雪碧有白泡泡 「个人网站」:雪碧的个人网站 「推荐专栏」: ★java一站式服务 ★ ★ React从入门到精通★ ★前端炫酷代码分享 ★ ★ 从0到英雄,vue成神之路★ ★ uniapp-从构建到提升★ ★ 从0到英雄ÿ…...

VMware Workstation里面安装ubuntu20.04的流程
文章目录 前言一、获取 desktop ubuntu20.04 安装镜像二、VMware Workstation下安装ubuntu20.041. VMware Workstation 创建一个新的虚拟机2. ubuntu20.04的安装过程3. 登录ubuntu20.044. 移除 ubuntu20.04 安装镜像总结参考资料前言 本文主要介绍如何在PC上的虚拟机(VMware W…...

pnpm的环境安装以及安装成功后无法使用的问题
文章目录 前言1、使用npm 安装2、安装后的注意点3、遇到问题4、配置path的环境变量(1)找到环境变量(2)找到并双击path的系统变量(3)复制第1步中使用npm安装的红框部分的路径(4)将第&…...

华为eNSP配置专题-浮动路由及BFD的配置
文章目录 华为eNSP配置专题-浮动路由及BFD的配置0、参考文档1、前置环境1.1、宿主机1.2、eNSP模拟器 2、基本环境搭建2.1、基本终端构成和连接2.2、基本终端配置 3、浮动路由配置3.1、浮动路由的基本配置3.2、浮动路由的负载均衡问题3.3、浮动路由的优先级调整 4、BFD的配置4.1…...

光储并网直流微电网simulink仿真模型,光伏采用mppt实现最大功率输出研究
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
面试题-React(十六):理解Redux及其工作原理
在现代前端开发中,状态管理是一个关键的问题。Redux是一个广泛使用的状态管理库,可以帮助开发者更有效地管理应用的状态。 一、什么是Redux? Redux是一个JavaScript状态管理库,用于管理应用中的状态(state࿰…...
Python|GIF 解析与构建(5):手搓截屏和帧率控制
目录 Python|GIF 解析与构建(5):手搓截屏和帧率控制 一、引言 二、技术实现:手搓截屏模块 2.1 核心原理 2.2 代码解析:ScreenshotData类 2.2.1 截图函数:capture_screen 三、技术实现&…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...
GitHub 趋势日报 (2025年06月08日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...

多模态大语言模型arxiv论文略读(108)
CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题:CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者:Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)
RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发,后来由Pivotal Software Inc.(现为VMware子公司)接管。RabbitMQ 是一个开源的消息代理和队列服务器,用 Erlang 语言编写。广泛应用于各种分布…...
区块链技术概述
区块链技术是一种去中心化、分布式账本技术,通过密码学、共识机制和智能合约等核心组件,实现数据不可篡改、透明可追溯的系统。 一、核心技术 1. 去中心化 特点:数据存储在网络中的多个节点(计算机),而非…...

VisualXML全新升级 | 新增数据库编辑功能
VisualXML是一个功能强大的网络总线设计工具,专注于简化汽车电子系统中复杂的网络数据设计操作。它支持多种主流总线网络格式的数据编辑(如DBC、LDF、ARXML、HEX等),并能够基于Excel表格的方式生成和转换多种数据库文件。由此&…...
React从基础入门到高级实战:React 实战项目 - 项目五:微前端与模块化架构
React 实战项目:微前端与模块化架构 欢迎来到 React 开发教程专栏 的第 30 篇!在前 29 篇文章中,我们从 React 的基础概念逐步深入到高级技巧,涵盖了组件设计、状态管理、路由配置、性能优化和企业级应用等核心内容。这一次&…...