2. Spring 注解开发

news2024/9/20 16:50:08

文章目录

  • 1. 用注解开发定义bean
  • 2. 纯注解开发
  • 3. 注解开发的 bean 管理
    • 3.1 作用范围管理(单例或非单例)
    • 3.2 生命周期管理
  • 4. 注解开发的依赖注入
    • 4.1 引用类型的依赖注入
    • 4.2 简单类型的依赖注入
      • 4.2.1 直接注入值
      • 4.2.2 注入 properties 文件中的值
  • 5. 注解开发与第三方 bean
    • 5.1 管理第三方 bean
    • 5.2 为第三方 bean 注入资源
      • 5.2.1 注入简单类型
      • 5.2.2 注入引用类型
  • 6. xml 配置 VS 注解配置

1. 用注解开发定义bean

@Component("bookDao")//相当于配置了bean,并指定了id
public class BookDaoImpl implements BookDao {
    @Override
    public void save() {
        System.out.println("book dao save...");
    }
}
//相当于配置了bean,但未指定id
//这里还没有 bookDao 的依赖注入,后面会讲到
@Component
public class BookServiceImpl implements BookService {
    private BookDao bookDao;

    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }

    @Override
    public void save() {
        System.out.println("book service save...");
        bookDao.save();
    }
}
<?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/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context.xsd">
           <!--1. 开启context命名空间-->
           
        <!--让配置文件能够扫描到类上的注解-->
        <!--base-package="com.itheima":扫描com.itheima下的所有类-->
        <context:component-scan base-package="com.itheima"/>

</beans>
public class AnnotationBeanApp {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        BookDao bookDao = (BookDao) ctx.getBean("bookDao");
        System.out.println(bookDao);
        //没有id,按类型取
        BookService bookService = ctx.getBean(BookService.class);
        System.out.println(bookService);
    }
}

输出结果:

com.itheima.dao.impl.BookDaoImpl@5e4c8041
com.itheima.service.impl.BookServiceImpl@fdefd3f

Spring 提供了 @Component 注解的三个衍生注解:
@Controller:用于表现层(servelt) bean 定义
@Service:用于业务层(service) bean 定义
@Repository:用于数据层(dao) bean 定义

有了上面三个衍生注解,BookDaoImpl 的 bean 可以用 @Repository 配置,BookServiceImpl 的 bean 可以用 @Service 配置。这样增强可读性。

2. 纯注解开发

Spring 3.0 升级了纯注解开发模式,使用 Java 类替代配置文件,开启了 spring 快速开发赛道。

(1) 类上的注解与上节相同

@Component("bookDao")//相当于配置了bean,并指定了id
public class BookDaoImpl implements BookDao {
    @Override
    public void save() {
        System.out.println("book dao save...");
    }
}
//相当于配置了bean,但未指定id
//这里还没有 bookDao 的依赖注入,后面会讲到
@Component
public class BookServiceImpl implements BookService {
    private BookDao bookDao;

    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }

    @Override
    public void save() {
        System.out.println("book service save...");
        bookDao.save();
    }
}

(2) 用一个配置类代替配置文件的功能:新建配置类,并告诉配置类扫描哪个目录下的 bean。
在这里插入图片描述

(3) 加载配置时有所不同,其余都与上节相同

public class AppForAnnotation {
    public static void main(String[] args) {
        // 加载配置类
        ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        BookDao bookDao = (BookDao) ctx.getBean("bookDao");
        System.out.println(bookDao);
        //没有id,按类型取
        BookService bookService = ctx.getBean(BookService.class);
        System.out.println(bookService);
    }
}

输出结果:

com.itheima.dao.impl.BookDaoImpl@255b53dc
com.itheima.service.impl.BookServiceImpl@4f9a3314

@Configuration 注解用于设定当前类为配置类
@ComponentScan 注解用于设定扫描路径,此注解只能添加一次,多个数据用数组格式

@ComponentScan({"com.itheima.service","com.itheima.dao"})

3. 注解开发的 bean 管理

3.1 作用范围管理(单例或非单例)

@Scope(“singleton”):单例
@Scope(“prototype”):非单例
默认单例

@Repository("bookDao")
@Scope("prototype")//非单例
public class BookDaoImpl implements BookDao {
    @Override
    public void save() {
        System.out.println("book dao save...");
    }
}

3.2 生命周期管理

@Repository("bookDao")
public class BookDaoImpl implements BookDao {
    @Override
    public void save() {
        System.out.println("book dao save...");
    }

    @PostConstruct//在构造方法后执行
    public void init(){
        System.out.println("init...");
    }

    @PreDestroy//在bean销毁前执行
    public void destroy(){
        System.out.println("destory...");
    }
}
@Configuration
@ComponentScan("com.itheima")
public class SpringConfig {
}
public class App {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        BookDao bookDao1 = (BookDao) ctx.getBean("bookDao");
        BookDao bookDao2 = (BookDao) ctx.getBean("bookDao");
        System.out.println(bookDao1);
        System.out.println(bookDao2);
        ctx.close();//关闭容器,以执行bean的销毁方法
    }
}

输出结果:

init...
com.itheima.dao.impl.BookDaoImpl@62e136d3
com.itheima.dao.impl.BookDaoImpl@62e136d3
destory...

4. 注解开发的依赖注入

4.1 引用类型的依赖注入

(1) 按类型装配@Autowired

@Repository//相当于配置了bean(创建对象)
public class BookDaoImpl implements BookDao {
    @Override
    public void save() {
        System.out.println("book dao save...");
    }
}
@Service//相当于配置了bean(创建对象)
public class BookServiceImpl implements BookService {
    @Autowired//按类型装配
    private BookDao bookDao;
	//不需要set方法了
    // public void setBookDao(BookDao bookDao) {
    //     this.bookDao = bookDao;
    // }

    @Override
    public void save() {
        System.out.println("book service save...");
        bookDao.save();
    }
}
@Configuration
@ComponentScan("com.itheima")
public class SpringConfig {
}
public class App {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        BookService bookService = ctx.getBean(BookService.class);
        bookService.save();
    }
}

输出结果:

book service save...
book dao save...

(2) 按名称装配
@Autowired
@Qualifier("bookDao2")
在(1)的例子中,若同时有:

@Repository("bookDao1")
public class BookDaoImpl implements BookDao {
    @Override
    public void save() {
        System.out.println("book dao save...");
    }
}
@Repository("bookDao2")
public class BookDaoImpl implements BookDao {
    @Override
    public void save() {
        System.out.println("book dao save...");
    }
}

则按类型装配就不行了,此时可以按名称装配。

@Autowired//不可省略
@Qualifier("bookDao2")//按名称装配
private BookDao bookDao;

输出结果:

book service save...
book dao save2...

【注意】

  • 自动装配基于反射设计创建对象并暴力反射对应属性为私有属性初始化数据,因此无需提供 setter 方法。
  • 自动装配建议使用无参构造方法创建对象(默认),如果不提供对应构造方法,请提供唯一的构造方法。
  • @Qualifier 注解无法单独使用,必须配合 @Autowired 注解使用。

4.2 简单类型的依赖注入

4.2.1 直接注入值

@Value("itheima")
private String name;

4.2.2 注入 properties 文件中的值

(1) jdbc.properties

name=itheima888

(2) 在配置类 SpringConfig.java 中加载 properties 文件

在这里插入图片描述
【注】多文件应使用数组格式配置@PropertySource({"jdbc1.properties","jdbc2.properties"})
不允许使用通配符,*.propertiesclasspath*:jdbc.properties都不行,classpath:jdbc.properties可以。

(3) 注入值

在这里插入图片描述

5. 注解开发与第三方 bean

5.1 管理第三方 bean

方式1:在配置类中直接获取第三方 bean。

@Configuration
public class SpringConfig {
    // 1.定义一个方法,获取要管理的对象
    // 2.添加@bean,表示当前方法的返回值是一个bean
    @Bean//可以写成@Bean("dataSource")
    public DataSource dataSource(){//方法名建议:要管理的bean的id名称
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName("com.mysql.jdbc.driver");
        ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
        ds.setUsername("root");
        ds.setPassword("root");
        return ds;
    }
}
public class App {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        DataSource dataSource = ctx.getBean(DataSource.class);
        System.out.println(dataSource);
    }
}

缺点:若要获取多个第三方 bean,配置类会十分庞大。

方式 2:新建 JdbcConfig 类,将获取第三方 bean 的方法剪切到该类中,并添加 @Configuration 注解。

在这里插入图片描述

为 SpringConfig 添加扫描 bean 的注解

@Configuration
@ComponentScan("com.itheima.config")//扫描bean
public class SpringConfig {

}

但是,该方法也不推荐,因为 JdbcConfig 类上也有 @Configuration 注解,显得有点乱;而且通过 SpringConfig 上的 @ComponentScan(“com.itheima.config”) 也看不出到底加载了哪些注解。

方式 3:去掉 JdbcConfig 上的 @Configuration 注解,用 @Import 引入。

在这里插入图片描述
引入多个类时,用数组:@Import({JdbcConfig.class,JdbcConfig1.class})

5.2 为第三方 bean 注入资源

5.2.1 注入简单类型

为第三方 bean 注入简单类型用成员变量的方式。

public class JdbcConfig {

    @Value("com.mysql.jdbc.driver")
    private String driver;
    @Value("jdbc:mysql://localhost:3306/spring_db")
    private String url;
    @Value("root")
    private String userName;
    @Value("root")
    private String password;

    @Bean
    public DataSource dataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(userName);
        ds.setPassword(password);
        return ds;
    }
}

5.2.2 注入引用类型

引用类型注入:为 bean 定义的方法设置形参即可,容器会根据类型自动装配对象。

在这里插入图片描述

public class JdbcConfig {

    @Value("com.mysql.jdbc.driver")
    private String driver;
    @Value("jdbc:mysql://localhost:3306/spring_db")
    private String url;
    @Value("root")
    private String userName;
    @Value("root")
    private String password;

    //检测到该方法要配置一个bean,就认为需要提供形参,所以bookDao进行了自动装配
    @Bean
    public DataSource dataSource(BookDao bookDao){
        System.out.println(bookDao);
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(userName);
        ds.setPassword(password);
        return ds;
    }
}
@Repository
public class BookDaoImpl implements BookDao {
    @Override
    public void save() {
        System.out.println("book dao save...");
    }
}
@Configuration
@ComponentScan("com.itheima")//扫描bookDao
@Import(JdbcConfig.class)
public class SpringConfig {
}
public class App {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        DataSource dataSource = ctx.getBean(DataSource.class);
        System.out.println(dataSource);
    }
}

输出结果:

com.itheima.dao.impl.BookDaoImpl@7bd4937b
{
	CreateTime:"2023-01-28 21:08:42",
	ActiveCount:0,
	PoolingCount:0,
	CreateCount:0,
	DestroyCount:0,
	CloseCount:0,
	ConnectCount:0,
	Connections:[
	]
}

6. xml 配置 VS 注解配置

在这里插入图片描述
红色标注的是十分常用的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/182766.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Acwing---1101. 献给阿尔吉侬的花束

献给阿尔吉侬的花束1.题目2.基本思想3.代码实现1.题目 阿尔吉侬是一只聪明又慵懒的小白鼠&#xff0c;它最擅长的就是走各种各样的迷宫。 今天它要挑战一个非常大的迷宫&#xff0c;研究员们为了鼓励阿尔吉侬尽快到达终点&#xff0c;就在终点放了一块阿尔吉侬最喜欢的奶酪。…

MYSQL不存在插入 存在更新的解决方法和对比

设置主键id自增&#xff0c;name为唯一索引 一、避免重复插入 insert ignore into&#xff08;有唯一索引&#xff09; 关键字/句: insert ignore into&#xff0c;如果插入的数据会导致 UNIQUE索引 或 PRIMARY KEY 发生冲突/重复&#xff0c;则忽略此次操作/不插入数据&…

Leetcode.1664 生成平衡数组的方案数

题目链接 Leetcode.1664 生成平衡数组的方案数 题目描述 给你一个整数数组 nums。你需要选择 恰好 一个下标&#xff08;下标从 0 开始&#xff09;并删除对应的元素。请注意剩下元素的下标可能会因为删除操作而发生改变。 比方说&#xff0c;如果 nums[6,1,7,4,1]nums [6,1…

spark转化操作

文章目录转化操作Transformer算子概念单RDD转换函数多RDD转换函数map与flatmap转化操作 由于spark的惰性计算特性&#xff0c;RDD只有在第一次行动操作中被用到时才会真正进行计算&#xff0c;因此我打算将文章内容分为"转化操作"和"行动操作"两部分&…

【web】微信小程序笔记小结(视图与逻辑)

过完年回来干正事了orz 来源&#xff1a;黑马程序员前端微信小程序开发教程 目录 I. 页面导航 ① 概念 ② 导航方式 1&#xff09;声明式导航 ※※ 导航到 tabBar 页面 ※※ 导航到非 tabBar 页面 ※※ 后退导航 2&#xff09;编程式导航 ※※ 导航到 tabBar 页面…

Nature立新规:ChatGPT等大模型不可以成为作者

众所周知&#xff0c;AI 的超参数决定着模型学习效果和速度。相比普通机器学习任务&#xff0c;深度学习需要的训练时间较长&#xff0c;因此调参技巧就显得尤为重要。 但鉴于深度学习「炼丹」的特性&#xff0c;不同的模型需要不同的超参数&#xff0c;而每个超参的意义又不同…

【头歌】汉诺塔(Hanoi)的递归算法

任务描述本关任务&#xff1a;汉诺塔(Hanoi)的递归算法。相关知识相传在古印度圣庙中&#xff0c;有一种被称为汉诺塔(Hanoi)的游戏。该游戏是在一块铜板装置上&#xff0c;有三根杆(编号A、B、C)&#xff0c;在A杆自下而上、由大到小按顺序放置64个金盘(如下图)。游戏的目标&a…

C语言中数组变量作为函数参数传值的两种方式:数组类型 指针类型 以及“C语言中数组变量(名)的本质是指针变量”

文章目录Intro & SummaryCode & Output运行截图Code关于数组长度在被调函数中的计算错误运行截图 & 警告信息Code数组变量是一类特殊的、指向自己的指针变量Intro & Summary 我在 main 函数中定义了一个数组&#xff0c;要将该数组作为参数传递给其他方法。那…

Lesson 4.3 梯度下降(Gradient Descent)基本原理与手动实现

文章目录一、梯度下降基本原理与学习率1. 数据背景与最小二乘法求解2. 一维梯度下降基本流程2.1 参数移动第一步2.2 梯度下降的多轮迭代3. 梯度下降算法特性与学习率二、梯度下降一般建模流程与多维梯度下降1. 多维梯度下降与损失函数可视化2. 梯度下降计算流程3. 二维梯度下降…

jvm学习的核心(四)---执行引擎和字符串

知识点总结于b站宋红康老师&#xff0c;视频链接 文章目录1.执行引擎1.1.执行引擎概述1.2.执行引擎的工作流程1.3.jvm的解释器和即时编译器&#xff08;JIT&#xff09;1.3.1.解释器&#xff0c;即时编译器概述1.3.2.常见即时编译器1.3.3.热点代码探测1.String Table1.1 string…

Go语言基础入门第三章

常量 常量是一个简单值的标识符&#xff0c;在程序运行时&#xff0c;不会被修改的量。 常量中的数据类型只可以是布尔型、数字型&#xff08;整数型、浮点型和复数&#xff09;和字符串型。 const identifier [type] value可以省略类型说明符[type]&#xff0c;因为编译器…

法律常识(三)《合同法》中的借款合同租赁合同摘录

目录 参考 一、借款合同 二、租赁合同 参考 中华人民共和国合同法 一、借款合同 第一百九十六条 借款合同是借款人向贷款人借款&#xff0c;到期返还借款并支付利息的合同。 第一百九十七条 借款合同采用书面形式&#xff0c;但自然人之间借款另有约定的除外。借款合同…

瑞吉外卖 对象转换器 公共字段自动填充 文件上传/下载

https://blog.csdn.net/weixin_43715214/category_12022798.html大佬记录项目介绍day01功能架构&#xff08;1&#xff09;用户层本项目中在构建系统管理后台的前端页面&#xff0c;我们会用到H5、Vue.js、ElementUI等技术。而在构建移动端应用时&#xff0c;我们会使用到微信小…

Red Giant Magic Bullet Suite介绍

Red Giant Magic Bullet Suite介绍什么是Magic Bullet SuiteMagic Bullet Suite功能介绍什么是Magic Bullet Suite Magic Bullet Suite是电影制作人不可或缺的一套调色降噪插件&#xff0c;它能够为您制作出和好莱坞一样的效果&#xff0c;为电影制作人提供专业的色彩校正。可…

excel函数应用:最简单的条件求和函数DSUM

SUM系列求和函数是我们日常工作中最常用的函数&#xff0c;相信大部分朋友对SUMIF、SUMIFS、SUMPRODUCT等函数都已经比较熟悉了。但是有一个求和函数大家可能都不熟悉&#xff0c;它就是DSUM函数&#xff0c;用于求数据库中记录的满足给定条件的的字段&#xff08;列&#xff0…

在中国社科院与美国杜兰大学金融管理硕士项目就读,重焕青春活力

在职场摸爬滚打多年后的你&#xff0c;是否有觉得内心疲惫&#xff1f; 是否进入到职场倦怠期&#xff1f;今天是春节后的首个工作日&#xff0c;新的一年意味着新的开始。你有想过在职继续攻读硕士学位吗&#xff1f;在中国社科院与美国杜兰大学金融管理硕士项目就读&#xff…

vue中实现打印

一、VUE 集成 LODOP插件打印 VUE 集成LODOP插件打印 Lodop、C-Lodop使用说明及样例 C-Lodop插件官网&#xff1a;功能演示 - Lodop和C-Lodop官网主站 参考文章&#xff1a;VUE 集成 LODOP插件打印_廷贺的博客-CSDN博客 二、winodw.print() 打印 print() 方法用于打印当前…

vs2015软件打包及常见问题解决方法

一、如程序文件是64位&#xff0c;而项目设置32位&#xff0c;打包项目编译时遇到如下问题 解决办法&#xff1a;选择打包程序项目的属性窗口设置TargetPlatform属性为对应的值&#xff0c;本项目的文件是64位的所以设置打包生成的程序为64位的&#xff0c;如下&#xff1a; …

【可解释性机器学习】排列重要性(Permutation Importance)及案例分析详解

Permutaion Importance&#xff1a;排列重要性引言工作原理代码示例排列重要性结果解读模型检验特征选择补充分析Partial Dependency PlotSharpley ValueLIME总结参考资料当训练得到一个模型之后&#xff0c;除了对模型的预测感兴趣之外&#xff0c;我们往往还想知道模型中哪些…

DDOS渗透与攻防(三)之socktress攻击

系列文章 DDOS渗透与攻防(一)之拒绝服务攻击概念介绍 DDOS渗透与攻防(二)之SYN-Flood攻击 socktress攻击 攻击协议原理介绍说明-socktress 2008年有Jack C.Louis发现&#xff0c;针对TCP服务的拒绝服务攻击&#xff1a; 消耗被攻击目标系统资源&#xff0c;与攻击目标建立…