Bean的注解开发

目录

注解定义bean

在实现类使用注解@Component

注意Spring提供了@Component注解的三个衍生注解

纯注解开发

bean管理

 bean的作用范围

bean的生命周期

bean的依赖注入

引用类型的注入 

如果有两个实现类呢(即有两个相同变量类型的bean),那该怎么办?

 简单类型的注入

 配置第三方Bean

获取Bean

抽取出新的配置类


注解定义bean

在实现类使用注解@Component

@Component
public class BookDaoImpl implements BookDao {public void update(){System.out.println("BookDao");}
}

那么spring怎么知道它要被定义成bean,所以在springConfig.xml文件中配置

<?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
"><context:component-scan base-package="com.hhh.dao"></context:component-scan>
</beans>

使用<context:component-scan>标签指定扫描包

public class App {public static void main(String[] args) {//加载配置文件,初始化容器ApplicationContext ctx=new ClassPathXmlApplicationContext("springConfig.xml");//容器中获取beanBookDao bookDao = ctx.getBean(BookDao.class);//或者BookDao bookDao = ctx.getBean(BookDaoImpl.class);bookDao.update();}
}

 除了可以通过类.class的方式来获取bean还可以通过id来获取bean,我们没有在<bean>标签中定义id名,那么对应的bean对象的id名是什么呢?

如果实现类的命名是驼峰式,那么id名就是开头字母小写,如果不是驼峰式,类名就是id名

public class App {public static void main(String[] args) {//加载配置文件,初始化容器ApplicationContext ctx=new ClassPathXmlApplicationContext("springConfig.xml");//容器中获取bean//BookDao bookDao = ctx.getBean(BookDao.class);//或者BookDao bookDao = ctx.getBean(BookDaoImpl.class);BookDao bookDao= (BookDao) ctx.getBean("bookDaoImpl");bookDao.update();}
}

 我们也可以直接使用注解@Component的value属性来赋值,值就是id名

@Component("bookDao1")
public class BookDaoImpl implements BookDao {public void update(){System.out.println("BookDao");}
}

public class App {public static void main(String[] args) {//加载配置文件,初始化容器ApplicationContext ctx=new ClassPathXmlApplicationContext("springConfig.xml");//容器中获取bean//BookDao bookDao = ctx.getBean(BookDao.class);//或者BookDao bookDao = ctx.getBean(BookDaoImpl.class);//BookDao bookDao= (BookDao) ctx.getBean("bookDaoImpl");BookDao bookDao= (BookDao) ctx.getBean("bookDao1");bookDao.update();}
}

注意Spring提供了@Component注解的三个衍生注解

  • @Controller:用于表现层(web)bean的定义
  • @Service:用于业务层(service)bean的定义
  • @Repository:用于数据层(dao)bean的定义
@Repository("bookDao1")
public class BookDaoImpl implements BookDao {public void update(){System.out.println("BookDao");}
}

 

可以发现@Repository其实和@Component注解的功能基本一样,但是这样把三层架构的注解区别,更美观,也更有利于管理 

纯注解开发

spring3.0升级了纯注解开发,使用java类代替配置文件。

@Configuration
@ComponentScan("com.hhh.dao")
public class SpringConfig {
}

使用两个注解

@Configuration说明这个类是配置文件

@ComponentScan说明这个配置文件要扫描的包

使用(先把配置文件删除):

public class App {public static void main(String[] args) {//加载配置文件,初始化容器//ApplicationContext ctx=new ClassPathXmlApplicationContext("springConfig.xml");//不使用配置文件初始化容器,加载配置类ApplicationContext ctx=new AnnotationConfigApplicationContext(SpringConfig.class);//容器中获取bean//BookDao bookDao = ctx.getBean(BookDao.class);//或者BookDao bookDao = ctx.getBean(BookDaoImpl.class);//BookDao bookDao= (BookDao) ctx.getBean("bookDaoImpl");BookDao bookDao= (BookDao) ctx.getBean("bookDao1");bookDao.update();}
}

 那如果要扫描两个包呢?

@Configuration
@ComponentScan({"com.hhh.dao","com.hhh.service"})
public class SpringConfig {
}

bean管理

 bean的作用范围

之前我们需要在<bean>标签中的scope属性来配置,现在我们只需要在实现类的开头使用注解@Scope即可

@Repository("bookDao1")
@Scope("prototype")
//多例
public class BookDaoImpl implements BookDao {public void update(){System.out.println("BookDao");}
}

bean的生命周期

在配置文件中我们需要使用init-method,destroy-method来配置初始方法和销毁方法

现在我们只需要用  @PostConstruct定义初始方法,@PreDestroy定义销毁方法

@Repository("bookDao1")
//@Scope("prototype")
public class BookDaoImpl implements BookDao {public void update(){System.out.println("BookDao");}@PostConstructpublic void init(){System.out.println("init");}@PreDestroypublic void destroy(){System.out.println("destroy");}
}

如果这两个注解失效,是因为@PostConstruct 和 @PostDestroy 注释都是Java EE的一部分。而且由于Java EE在Java 9中已被弃用,而在Java 11中已被删除

所以只需要在pom.xml中加上

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

 使用

public class App {public static void main(String[] args) {//加载配置文件,初始化容器//ApplicationContext ctx=new ClassPathXmlApplicationContext("springConfig.xml");//不使用配置文件初始化容器AnnotationConfigApplicationContext ctx=new AnnotationConfigApplicationContext(SpringConfig.class);//容器中获取bean//BookDao bookDao = ctx.getBean(BookDao.class);//或者BookDao bookDao = ctx.getBean(BookDaoImpl.class);//BookDao bookDao= (BookDao) ctx.getBean("bookDaoImpl");BookDao bookDao= (BookDao) ctx.getBean("bookDao1");bookDao.update();ctx.close();//bookDao.update();}
}

结果:

bean的依赖注入

service层

引用类型的注入 


@Service
public class BookServiceImpl implements BookService {@Autowired//根据变量类型自动依赖注入private BookDao bookDao;public void update(){bookDao.update();System.out.println("BookService");}
}

 使用注解@AutoWired即可实现依赖注入,原理是在容器中寻找有没有与这个变量类型一致的bean对象,如果有就直接依赖注入。

可以发现使用注解不用写setter方法,因为直接使用的暴力反射进行赋值

如果有两个实现类呢(即有两个相同变量类型的bean),那该怎么办?

不处理就会报错

No qualifying bean of type 'com.hhh.dao.BookDao' available: expected single matching bean but found 2: bookDao1,bookDaoImpl2
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:643)

如果有和变量名一致的id(前提:类型一致)那么就可以直接赋值,不会报错

但是使用注解@Qualifier可以直接指定使用哪个bean

注意@Qualifier不可单独使用,必须和@AutoWired一起用

@Service
public class BookServiceImpl implements BookService {@Autowired@Qualifier("bookDao2")//使用id名为bookDao2的实现类对象//根据变量类型自动依赖注入private BookDao bookDao;public void update(){bookDao.update();System.out.println("BookService");}
}

结果:

 简单类型的注入

使用注解@Value

@Service
public class BookServiceImpl implements BookService {@Autowired@Qualifier("bookDao2")//根据变量类型自动依赖注入private BookDao bookDao;@Value("hhh")private String name;@Value("foo,bar,fun")private List<String> list;public void update(){bookDao.update();System.out.println("BookService");System.out.println("name="+name);System.out.println(list);}
}

注入外部文件

现在SpringConfig类中添加注解@PropertySource

@Configuration
@ComponentScan({"com.hhh.dao","com.hhh.service"})
@PropertySource("classpath:jdbc.properties")//加载名字为dbc.properties的文件
public class SpringConfig {
}

这是文件的内容

@Service
public class BookServiceImpl implements BookService {@Autowired@Qualifier("bookDao2")//根据变量类型自动依赖注入private BookDao bookDao;@Value("hhh")private String name;@Value("foo,bar,fun")private List<String> list;@Value("${jdbc.username}")//去加载文件的key为username的value值private String nm;public void update(){bookDao.update();System.out.println("BookService");System.out.println("name="+name);System.out.println(list);System.out.println(nm);}
}

 配置第三方Bean

先导入坐标

<dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.16</version></dependency>
@Configuration
@ComponentScan({"com.hhh.dao","com.hhh.service"})
@PropertySource("jdbc.properties")
public class SpringConfig {@Beanpublic DataSource getDataSource(){DruidDataSource druidDataSource = new DruidDataSource();return druidDataSource;}
}

使用注解@Bean让这个方法的返回值变成Bean(交给Spring容器管理),默认id为方法名

获取Bean


public class App {public static void main(String[] args) {//不使用配置文件初始化容器AnnotationConfigApplicationContext ctx=new AnnotationConfigApplicationContext(SpringConfig.class);//第一种方法://DataSource dataSource = ctx.getBean(DataSource.class);//使用类//第二种方法:使用id名,id名为方法名Object dataSource = ctx.getBean("getDataSource");System.out.println(dataSource);}
}

 或者直接使用@Bean的属性直接配置id名,这样一来id就不是方法名了


@Configuration
@ComponentScan({"com.hhh.dao","com.hhh.service"})
@PropertySource("jdbc.properties")
public class SpringConfig {@Bean("dataSource")public DataSource getDataSource(){DruidDataSource druidDataSource = new DruidDataSource();return druidDataSource;}
}

抽取出新的配置类

可以发现这是数据源的配置文件,可以把它从Spring的配置文件中抽取出来

然后再SpringConfig类中使用@Import注解导入该文件即可 

@Configuration
@ComponentScan({"com.hhh.dao","com.hhh.service"})
@PropertySource("jdbc.properties")
@Import({jdbcConfig.class})
public class SpringConfig {}

或者

 直接再jdbcConfig类中直接用@Configuration注解,但是SpringConfig类的@ComponentScan要改成整个包,保证扫描到jdbcConfig类

 配置数据库的四个参数

public class jdbcConfig {@Value("${jdbc.url}")private String url;@Value("${jdbc.username}")private String name;@Value("${jdbc.driver}")private String driver;@Value("${jdbc.password}")private String password;@Bean("dataSource")public DataSource getDataSource(){System.out.println("driver="+driver);DruidDataSource druidDataSource = new DruidDataSource();druidDataSource.setUrl(url);druidDataSource.setDriverClassName(driver);druidDataSource.setName(name);druidDataSource.setPassword(password);return druidDataSource;}
}

使用的是SpringConfig导入了jdbc.properties文件

 如果需要使用引用数据类型,直接再方法里的参数里写,它就会自己注入,不需要@Autowire注解

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

maven内网依赖包编译报错问题的一种解决方法

背景 外网开发时可以连接互联网&#xff0c;所以编译没有什么问题&#xff0c;但是将数据库、代码、maven仓库全部拷贝到内网&#xff0c;搭建内网环境之后&#xff0c;编译失败。 此依赖包的依赖层级图 maven镜像库配置使用拷贝到内网的本地库&#xff0c;配置如下&#xff…

从操作系统层面认识Linux

描述进程-PCB Linux操作系统下的PCB是: task_struct https://www.cnblogs.com/tongyan2/p/5544887.htmlhttps://www.cnblogs.com/tongyan2/p/5544887.html校招必背操作系统面试题-什么是 PCB&#xff08;进程控制块&#xff09; &#xff1f;_哔哩哔哩_bilibili校招必背操作系…

FOG Project 文件名命令注入漏洞复现(CVE-2024-39914)

0x01 产品简介 FOG是一个开源的计算机镜像解决方案,旨在帮助管理员轻松地部署、维护和克隆大量计算机。FOG Project 提供了一套功能强大的工具,使用户能够快速部署操作系统、软件和配置设置到多台计算机上,从而节省时间和精力。该项目支持基于网络的 PXE 启动、镜像创建和还…

应用层——HTTP

像我们电脑和手机使用的应用软件就是在应用层写的&#xff0c;当我们的数据需要传输的时候换将数据传递到传输层。 应用层专门给用户提供应用功能&#xff0c;比如HTTP,FTP… 我们程序员写的一个个解决我们实际的问题都在应用层&#xff0c;我们今天来聊一聊HTTP。 协议 协议…

配置SMTP服务器的要点是什么?有哪些限制?

配置SMTP服务器安全性如何保障&#xff1f;如何高效配置服务器&#xff1f; SMTP作为电子邮件发送的核心协议&#xff0c;其配置对于确保邮件的成功传递和安全至关重要。AokSend将详细介绍配置SMTP服务器的关键要点&#xff0c;帮助读者建立一个高效、安全的邮件发送系统。 配…

【BUG】已解决:note: This is an issue with the package mentioned above,not pip.

已解决&#xff1a;note: This is an issue with the package mentioned above&#xff0c;not pip. 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#xff0c;我是博主英杰&#xff0c;211科班出身&#xff0c;就职于医疗科技公司&#xff0c;热衷…

【LabVIEW作业篇 - 3】:数组相加、for循环创建二位数组、数组练习(求最大最小值、平均值、中位数、提取范围内的数据、排序)

文章目录 数组相加for循环实现直接使用加函数 for循环创建二位数组数组练习 数组相加 要求&#xff1a;用两种方法实现两个数组相加 for循环实现 在前面板中分别创建两个数值类型的一维数组&#xff0c;并设置相应的值&#xff0c;然后在程序框图中创建一个for循环&#xff…

Android SurfaceView 组件介绍,挖洞原理详解

文章目录 组件介绍基本概念关键特性使用场景 SurfaceHolder介绍主要功能使用示例 SurfaceView 挖洞原理工作机制 使用SurfaceView展示图片示例创建一个自定义的 SurfaceView类在 Activity 中使用 ImageSurfaceView注意事项效果展示 组件介绍 在 Android 开发中&#xff0c;Sur…

uniapp-vue3-vite 搭建小程序、H5 项目模板

uniapp-vue3-vite 搭建小程序、H5 项目模板 特色准备拉取默认UniApp模板安装依赖启动项目测试结果 配置自动化导入安装依赖在vite.config.js中配置 引入 prerttier eslint stylelint.editorconfig.prettierrc.cjs.eslintrc.cjs.stylelintrc.cjs 引入 husky lint-staged com…

STM32智能家居电力管理系统教程

目录 引言环境准备智能家居电力管理系统基础代码实现&#xff1a;实现智能家居电力管理系统 4.1 数据采集模块 4.2 数据处理与控制模块 4.3 通信与网络系统实现 4.4 用户界面与数据可视化应用场景&#xff1a;电力管理与优化问题解决方案与优化收尾与总结 1. 引言 智能家居电…

SpringMVC注解全解析:构建高效Web应用的终极指南 (上)

SpringMVC 是一个强大的 Web 框架&#xff0c;广泛应用于 Java Web 开发中。它通过注解简化了配置&#xff0c;增强了代码的可读性。本文将全面解析 SpringMVC 中常用的注解及其用法&#xff0c;帮助你构建高效的 Web 应用。 一. MVC介绍 MVC 是 Model View Controller 的缩写…

Docker 镜像使用和安装

​ 1、简介 Docker是一个开源的应用容器引擎&#xff1b;是一个轻量级容器技术&#xff1b; Docker支持将软件编译成一个镜像&#xff1b;然后在镜像中各种软件做好配置&#xff0c;将镜像发布出去&#xff0c;其他使用者可以直接使用这个镜像&#xff1b; 运行中的这个镜像…

AI(Adobe lliustrator)教程+软件包

简介&#xff1a; 软件主要应用于印刷出版、海报书籍排版、专业插画、多媒体图像处理和互联网页面的制作等&#xff0c;也可以为线稿提供较高的精度和控制&#xff0c;适合生产任何小型设计到大型的复杂项目。 通常用于创建LOGO(商标或徽标)&#xff0c;图标&#xff0c;插图…

数据库管理的艺术(MySQL):DDL、DML、DQL、DCL及TPL的实战应用(上:数据定义与控制)

文章目录 DDL数据定义语言1、创建数据库2、创建表3、修改表结构4、删除5、数据类型 列的约束主键约束&#xff08;primary key&#xff09;唯一约束&#xff08;unique key&#xff09;非空约束检查约束&#xff08;check&#xff09;外键约束&#xff08;foreign key&#xff…

2024北京国际智能工厂及自动化展览会亮点前瞻

随着“工业创新&#xff0c;智造未来”的浪潮席卷而来&#xff0c;2024年度北京国际智能工厂及自动化与工业装配展览会定于8月1日至3日在中国国际展览中心&#xff08;顺义新馆&#xff09;盛大开幕。本次展会汇聚了智能制造与自动化技术的最新成果&#xff0c;通过三展联动的创…

Python基础语法篇(下)+ 数据可视化

Python基础语法&#xff08;下&#xff09; 数据可视化 一、函数&#xff08;一&#xff09;函数的定义&#xff08;二&#xff09;函数的调用和传参 二、文件操作&#xff08;一&#xff09;文件读取和写入&#xff08;二&#xff09;文件对象及方法&#xff08;三&#xff09…

UniVue@v1.5.0版本发布:里程碑版本

前言 以后使用UniVue都推荐使用1.5.0以后的版本&#xff0c;这个版本之后&#xff0c;更新的速度将会放缓。 希望这个框架能够切实的帮助大家更好的开发游戏&#xff0c;做出一款好游戏&#xff01;本开源项目采用的开源协议为MIT协议&#xff0c;完全开源化&#xff0c;以后也…

LinuxShell编程2——shell搭建Discuzz论坛网站

目录 一、环境准备 ①准备一台虚拟机 ②初始化虚拟机 1、关闭防火墙 2、关闭selinux 3、配置yum源 4、修改主机名 二、搭建LAMP环境 ①安装httpd(阿帕奇apache&#xff09;服务器 查看是否安装过httpd 启动httpd 设置开机启动 查看状态 安装网络工具 测试 ②安装…

神经网络中如何优化模型和超参数调优(案例为tensor的预测)

总结&#xff1a; 初级&#xff1a;简单修改一下超参数&#xff0c;效果一般般但是够用&#xff0c;有时候甚至直接不够用 中级&#xff1a;optuna得出最好的超参数之后&#xff0c;再多一些epoch让train和testloss整体下降&#xff0c;然后结果就很不错。 高级&#xff1a;…

紫光展锐5G安卓核心板T760__国产手机芯片方案

展锐T760安卓核心板是具备续航和性能更加均衡的5G移动平台。其主要特点包括主流的6400万像素摄像头和高达120Hz的刷新率。 平台采用多模融合的创新架构和AI智能调节技术&#xff0c;从而在5G数据场景下降低了37%的整体功耗&#xff0c;在5G待机场景下降低了18%的整体功耗。 多…