Spring-注解注入

news2024/12/23 3:27:24

一、回顾XML注解 bean 配置

  • 创建 bean

    public class Student {
    }
  • 配置 xml bean

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
        <bean id="student" class="cn.sycoder.xmlbean.Student"></bean>
    </beans>
  • 获取 bean

    @Test
    public void testXmlBean(){
        ApplicationContext context = new ClassPathXmlApplicationContext("xmlbeans.xml");
        final Student student = (Student)context.getBean("student");
        System.out.println(student);
    }

 1.存在问题

  • 需要写xml 配置,比较麻烦,而已获取也很麻烦
  • 注入属性也比较麻烦:构造器,setter

2.解决办法

  • 通过注解配置bean 以及注解操作 di 注入
  • 注解配置的优点:更简洁,更短,更方便

二、IOC 注解开发

  • 版本了解
    • 2.0版本时开始支持注解开发(2.0之前就是昨天学习的纯 xml 操作)
    • 2.5版本才完善
    • 3.0版本支持纯注解开发

1.注解&xml配置Bean

1.1配置用户mapper

  • 配置 mapper
public interface UserMapper {
    void save();
}
  •  配置 mapper 实现类(还没有交给 spring 管理)
public class UserMapperImpl implements UserMapper {
    public void save() {
        System.out.println("保存用户成功");
    }
}

1.2将mapper交给spring管理

使用 @Component 注解,配置 mapper 实现类

@Component
public class UserMapperImpl implements UserMapper {
    public void save() {
        System.out.println("保存用户成功");
    }
}

配置 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/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    <context:component-scan base-package="cn.wjcoder.xmlAnnotationBean.mapper"/>
</beans>

1.3通过容器获取bean

获取 applicationContext

@Test
public void testComponent(){
    ApplicationContext context = new ClassPathXmlApplicationContext("xmlAndAnnotation.xml");
    final UserMapper bean = context.getBean(UserMapper.class);
    bean.save();
}

1.4Component详解

  • 默认不传参,bean 的名称是首字母小写其余不变
正规命名的时候:UserMapperImpl --- userMapperImpl
不正规命名时候:UUserMapperImpl--- UUserMapperImpl
  • 给bean 指定名称
@Component("u") 参数就是你bean的名称
  • 使用位置:具体类的上方,不要使用到接口上
  • 作用:将bean 交给spring管理
  • 延伸的注解,注意,和Component一模一样的,只不过是用于给程序员区分业务组件的

Controller(控制层)  

@Controllerpublic class UserController {    //写接口}

Service(业务层)

@Service
public class UserServiceImpl implements IUserService {
    public void save() {
    }
}

Repository(持久层)

@Repository
public class UserMapperImpl implements UserMapper {
    public void save() {
        System.out.println("保存用户成功");
    }
}

2.纯注解配置Bean

2.1配置学生Mapper

mapper 接口

  public interface StudentMapper {
      void save();
  }

mapper 接口实现类

 @Repository
  public class StudentMapperImpl implements StudentMapper {
      public void save() {
          System.out.println("保存学生成功");
      }
  }

2.2添加配置类

  • @Configuration详解
  • 使用 @Configuration
 @Configuration
  public class SpringConfig {
  }

 将 SpringConfig 类变成spring 的配置类,替换 xml 配置文件

作用:标识该类是spring的配置类

配置名称,默认首字母小写

使用在类上

  • @ComponentScan详解

配置包扫描 @ComponentScan

  @Configuration
  @ComponentScan("cn.sycoder.annotationBean.mapper")
  public class SpringConfig {
  }

作用:配置包扫描路径,当前包及其子包都会扫描

value:指定包的路径,用于扫描并且注册bean

2.3获取bean

获取 applicationContext

  ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);

获取 bean
 

@Test
    public void testAnnotation(){
      ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
      System.out.println(context);
  
      final StudentMapper bean = context.getBean(StudentMapper.class);
      System.out.println(bean);
  }

3.注解开发与xml 的梳理

3.1使用@Component 替代 xml 的过程梳理

3.2使用 @Configuration @ComponentScan 与 xml 配置过程的梳理

4.bean scops

配置类

@Configuration
@ComponentScan({"cn.wjcoder.xmlAnnotationBean"})
public class ScopesConfig {
}

 配置 bean

@Component
public class ScopeBean {
}

 获取 bean 执行发现bean 单例的

@Test
    public void testScope(){
        ApplicationContext context = new AnnotationConfigApplicationContext(ScopesConfig.class);
        final ScopeBean bean = context.getBean(ScopeBean.class);
        final ScopeBean bean1 = context.getBean(ScopeBean.class);
        System.out.println(bean);
        System.out.println(bean1);
    }

4.1通过注解修改 scope(@Scope)

@Component
@Scope("prototype")
public class ScopeBean {
}

4.2@Scope 详解

  • 位置:定义到类上方
  • 作用:修改对象创建的作用域
  • 属性:默认是singleton(单例的),可以修改成 prototype(原型)

5.bean 生命周期常用注解

@Component
public class LifeBean {

    public LifeBean(){
        System.out.println("构造器执行了");
    }
    @PostConstruct
    public void init(){
        System.out.println("初始化bean");
    }
    @PreDestroy
    public void destroy(){
        System.out.println("销毁bean");
    }
}

5.1@PostConstruct详解

位置:方法上
作用:设置该方法为初始化方法

5.2@PreDestroy

位置:方法上
作用:设置该方法为销毁方法

5.3注解与 xml 的梳理

三、DI 注解开发

1.目前面临问题

  • 建立 mapper

    public interface EmployeeMapper {
        void save();
    }
  • 建立 mapper 实现类

    @Repository
    public class EmployeeMapperImpl implements EmployeeMapper {
        public void save(){
            System.out.println("保存员工信息");
        }
    }
  • 建立 service

    public interface IEmployeeService {
        void save();
    }
  • 建立 service 实现类

    @Service
    public class EmployeeServiceImpl implements IEmployeeService {
    ​
        private EmployeeMapper employeeMapper;
    ​
        public void setEmployeeMapper(EmployeeMapper employeeMapper){
            this.employeeMapper = employeeMapper;
        }
        public void save() {
            employeeMapper.save();
        }
    }
  • 设置配置类

    @Configuration
    @ComponentScan("cn.sycoder.di.di01")
    public class DiConfig {
    }
  • 出现空指针异常

2.使用类型注入

  • @Autowired按照类型注入

  • 通过构造器注入

    @Autowired
    public EmployeeServiceImpl(EmployeeMapper employeeMapper) {
        this.employeeMapper = employeeMapper;
    }
  • 通过setter 方法注入

    @Autowired
    public void setEmployeeMapper(EmployeeMapper employeeMapper) {
        this.employeeMapper = employeeMapper;
    }
  • 直接在属性上使用(是以后用得最多的)

    @Service
    public class EmployeeServiceImpl implements IEmployeeService {
    ​
        @Autowired
        private EmployeeMapper employeeMapper;
    ​
        public void save() {
            employeeMapper.save();
        }
    }
  • 注意:不提供setter 方法以及构造器是使用反射创建对象的

@Test
    public void autowired() throws Exception {
        final Class<?> aClass = Class.forName("cn.wjcoder.di.di01.service.EmployeeServiceImpl");
        final Object o = aClass.newInstance();
        final Field[] fields = aClass.getDeclaredFields();
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DiConfig.class);
        final EmployeeMapper bean = context.getBean(EmployeeMapper.class);
        for (Field field : fields) {
            field.setAccessible(true);
            field.set(o,bean);
        }
        final EmployeeServiceImpl service = (EmployeeServiceImpl) o;
        service.save();
    }
  • 根据类型注入必须只有一个实现类,否则会报错,添加名称也不行

  • 属性required=false,如果找不到不会报错

3.使用名称注入

  • @Autowired & @Qualifier

  • @Autowired & @Qualifier必须同时使用,缺一不可

  • 解决刚才出现两个实现类没法注入的问题

  • 配置mapper 并且指定实现类的名称

public interface EmployeeMapper {
    void save();
}

@Repository("empMapper1")
public class EmployeeMapperImpl implements EmployeeMapper{
    @Override
    public void save() {
        System.out.println("保存员工信息");
    }
}
@Repository("empMapper2")
public class EmployeeMapperImpl1 implements EmployeeMapper {
    private EmployeeMapper employeeMapper;

    public void save() {
        employeeMapper.save();
    }
}
  •  按照名称注入
@Service
public class EmployeeServiceImpl implements IEmployeeService {

    @Autowired(required = false)
    @Qualifier("empMapper1")
    private EmployeeMapper employeeMapper;

    public void save() {
        employeeMapper.save();
    }

}

4.简单数据类型注入

  • @Value

  • 修改配置类

    @Configuration
    @ComponentScan("cn.wjcoder.di.di01")
    @PropertySource("db.properties")
    public class DiConfig {
    }
  • 修改获取方式使用 ${} 的方式

    @Component
    public class DbProperties {
    ​
        @Value("${username}")
        private String username;
        @Value("${password}")
        private String password;
    ​
        public void test(){
            System.out.println(username + ":" + password);
        }
    }

5.1@PropertySource

  • @PropertySource 加载配置文件

  • 位置:配置类上

  • 作用导入配置文件

  • 对于多个配置文件

    @Configuration
    @ComponentScan("cn.wjcoder.di.di01")
    @PropertySource({"db.properties","xx.properties"})
    public class DiConfig {
    }

6.注解配置第三方bean

6.1配置 druid

  • 添加依赖

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.2.8</version>
    </dependency>
  • 先添加配置类 SpringConfig

    @Configuration
    public class SpringConfig {
    ​
    ​
        public DataSource dataSource(){
            final DruidDataSource source = new DruidDataSource();
            source.setUsername("root");
            source.setPassword("123456");
            source.setDriverClassName("com.mysql.cj.jdbc.Driver");
            source.setUrl("jdbc:mysql://localhost:3306/mybatis");
            return source;
        }
    ​
    }
  • 传统做法存在硬编码,DataSource 并且没有交给 spring 管理,每次都需要重新新建 DataSource ,并不存在单例一说

    @Test
        public void testDruid(){
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
            final SpringConfig bean = context.getBean(SpringConfig.class);
            System.out.println(bean.dataSource());
        }

6.2@Bean 配置 druid

  • 使用@Bean 交给 spring 管理

    @Configuration
    public class SpringConfig {
    ​
        @Bean
        public DataSource dataSource(){
            final DruidDataSource source = new DruidDataSource();
            source.setUsername("root");
            source.setPassword("123456");
            source.setDriverClassName("com.mysql.cj.jdbc.Driver");
            source.setUrl("jdbc:mysql://localhost:3306/mybatis");
            return source;
        }
    ​
    }
  • 修改配置的硬编码改成软编码

    @Configuration
    @PropertySource("druidDb.properties")
    public class SpringConfig {
        @Value("${jdbc.username}")
        private String username;
        @Value("${jdbc.password}")
        private String password;
        @Value("${jdbc.url}")
        private String url;
        @Value("${jdbc.driverClassName}")
        private String driver;
    ​
        @Bean
        public DataSource dataSource(){
            final DruidDataSource source = new DruidDataSource();
            source.setUsername(username);
            source.setPassword(password);
            source.setDriverClassName(driver);
            source.setUrl(url);
            return source;
        }
    ​
    }
    jdbc.username=root
    jdbc.password=123456
    jdbc.driverClassName=com.mysql.cj.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/mybatis
  • @Bean 与 xml 对应

7.使用@Import 实现配置导入

  • 目前存在:任何类都配置到配置类里面,不方便管理,也不方便维护

7.1配置 Component 解决

  • @Component

    @Component
    public class DruidConfig {
        @Value("{jdbc.username}")
        private String username;
        @Value("{jdbc.password}")
        private String password;
        @Value("{jdbc.url}")
        private String url;
        @Value("{jdbc.driverClassName}")
        private String driver;
    ​
    ​
        @Bean
        public DataSource dataSource(){
            final DruidDataSource source = new DruidDataSource();
            source.setUsername(username);
            source.setPassword(password);
            source.setDriverClassName(driver);
            source.setUrl(url);
            return source;
        }
    }

7.2使用@import

  • 修改druidConfig

    @Configuration
    public class DruidConfig {
        @Value("{jdbc.username}")
        private String username;
        @Value("{jdbc.password}")
        private String password;
        @Value("{jdbc.url}")
        private String url;
        @Value("{jdbc.driverClassName}")
        private String driver;
    ​
    ​
        @Bean
        public DataSource dataSource(){
            final DruidDataSource source = new DruidDataSource();
            source.setUsername(username);
            source.setPassword(password);
            source.setDriverClassName(driver);
            source.setUrl(url);
            return source;
        }
    }
  • 修改spring配置类

    @Configuration
    @PropertySource("druidDb.properties")
    @Import({DruidConfig.class})
    public class SpringConfig {
    }
  • 如果需要传参,只需要将参数交给spring管理就行了

    @Configuration
    public class RepositoryConfig {
         @Bean
         public AccountRepository accountRepository(DataSource dataSource) {
            return new JdbcAccountRepository(dataSource);
         }
    }

8.注解开发总结

注解配置xml 配置功能说明

@Component

@Controller

@Service

@Repository

bean 标签(id,class)定义bean
@ComponentScan<context:component-scan base-package="cn.sycoder.ioc.xmlAnnotationBean"/>扫描包加载bean

@Autowired

@Qualifier

@Value

setter 注入

构造器注入

自动装配

依赖注入
@Bean

bean 标签,

静态工厂模式,

实例工厂模式,

FactoryBean

配置第三方bean
@Scopebean 标签中的 scope 属性设置作用域

@PostConstructor

@PreDestroy

bean 标签中的 init-method / destroy-method生命周期相关
@Import导入其它的配置类
@PropertySource({"db.properties","xx.properties"})<context:property-placeholder system-properties-mode="NEVER" location="*.properties"/>导入配置文件

 

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

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

相关文章

2023年人工智能技术趋势

随着DALL-E 2、ChatGPT等越来越多应用的出现&#xff0c;人们越来越期待人工智能在2023年给人们带来的突破性改进。2023年人工智能技术趋势人工智能(AI)的应用越来越具有创新性&#xff0c;广泛的应用程序使用 AI 从头开始创建令人印象深刻的文本、视频和图像。越来越多的新应用…

【深度学习】扩散模型(Diffusion Model)详解

【深度学习】扩散模型&#xff08;Diffusion Model&#xff09;详解 文章目录【深度学习】扩散模型&#xff08;Diffusion Model&#xff09;详解1. 介绍2. 具体方法2.1 扩散过程2.2 逆扩散过程2.3 损失函数3. 总结4. 参考1. 介绍 扩散模型有两个过程&#xff1a; 扩散过程&…

蓝桥杯2012年省赛棋盘放麦子

题目描述 本题为填空题&#xff0c;只需要算出结果后&#xff0c;在代码中使用输出语句将所填结果输出即可。 你一定听说过这个故事。国王对发明国际象棋的大臣很佩服&#xff0c;问他要什么报酬&#xff0c;大臣说&#xff1a;请在第 11 个棋盘格放 11 粒麦子&#xff0c;在…

【宝藏博客系列】用C语言中的普通数组构建一棵特殊的完全二叉树----堆(内容超劲爆的喔~)

目录 0.前言 1. 用数组表示存储一棵完全二叉树 2. 数组表示的完全二叉树的性质 3. 堆的基本概念 3.1 堆的核心性质 3.2 堆顶的性质 3.3 堆的单支性质 3.4 堆的左右支关系 4. 用代码实现堆 4.1 堆类的实现 4.2 堆的初始化 4.3 堆的销毁 4.4 获取堆顶的数据 4.5 …

惠普电脑怎么录屏?图文教学,3种简单易懂的录屏方法

如果你需要在惠普电脑上录制视频或游戏&#xff0c;那么录屏软件是必不可少的工具。但是&#xff0c;有很多人不知道惠普电脑怎么录屏&#xff0c;或者不知道该选择哪种录屏软件进行录屏。今天小编将向小伙伴介绍3种简单易懂的惠普电脑录屏方法&#xff0c;帮助你轻松录制高质量…

信息系统基本知识(三)软件工程

1.4 软件工程 定义&#xff1a;将系统的、规范的、可度量的工程化方法应用于软件开发、运行和维护的全过程即上述方法的研究 软件工程由方法、工具和过程三个部分组成 1.4.1 需求分析 软件需求是指用户对新系统在功能、行为、性能、设计约束等方面的期望。 需求层次 业务…

FFmpeg入门 - Android移植

1、FFmpeg编译与集成FFmpeg的安卓交叉编译网上有很多的资料,基本上都是些编译配置而已。可以直接将我的脚本放到ffmpeg源码根目录,修改下NDK的路径和想要编译的ABI之后直接执行。然后就能在android目录里面得到编译好的so和.h如果的确编译出现问题,也可以直接用我编出来的库。将…

Enlight Software Ltd.官方正式推出〔金融帝国实验室试玩版本〕(Capitalism Lab Demo Version)

Enlight Software Ltd.官方正式推出〔金融帝国实验室试玩版本〕&#xff08;Capitalism Lab Demo Version&#xff09; ————————————— 与一般游戏的试玩版本不同&#xff0c;〔金融帝国实验室试玩版本〕是一款功能齐全的游戏&#xff0c;包含完整版本的所有功能…

spark sql(三)逻辑计划解析(analyzer)

1、前言 Spark SQL 逻辑计划在实现层面被定义为 LogicalPlan 类 。 从 SQL 语句经过 SparkSqlParser解析生成 Unresolved LogicalPlan &#xff0c;到最终优化成为 Optimized LogicalPlan &#xff0c;这个流程主要经过3 个阶段。 这 3 个阶段分别产生 Unresolved LogicalPlan,…

组合模式-文件目录管理

什么是组合模式&#xff1f; 组合模式是一种结构型设计模式&#xff0c;它允许你将对象组合成树形结构来表现"部分-整体"的层次结构。组合模式使得客户端可以统一地对待单个对象和对象组合&#xff0c;从而使得系统更加灵活。 在组合模式中&#xff0c;有两种基本类…

SQL开发管理工具,SQL Studio成数据库管理工具热门

达梦数据库冲击IPO成功&#xff1b;麒麟软件等国产Linux桌面操作系统在国防、教育等行业达到百万规模级应用&#xff1b;阿里云计算操作系统取得重大突破&#xff0c;阿里云市场份额全球第三&#xff1b;宝兰德、中创等厂商的应用服务器中间件能够实现对IBM和Oracle相关产品的替…

Linux学习第十一节-磁盘类型介绍和挂载

1.磁盘类型介绍 IDE接口类型&#xff1a;主要用于个人家用计算机领域&#xff0c;优点价格便宜&#xff0c;缺点数据传输速度慢&#xff1b; SCSI接口类型&#xff1a; 主要用于服务器领域&#xff0c;数据传输速度快&#xff0c;支持热插拔&#xff1b; SATA接口类型&…

Android Automotive 调节音量的过程

Android Automotive OS (AAOS) 是在核心 Android 系统的基础之上打造而成&#xff0c;以支持将 Android 系统用作车辆信息娱乐系统的场景。AAOS 的音频系统对核心 Android 音频系统做了扩充&#xff0c;创建了新的概念和抽象&#xff0c;如音区等&#xff0c;提供了新的 API 接…

〖大前端 - 基础入门三大核心之 html 篇⑩〗- 图片标签

大家好&#xff0c;我是 哈士奇 &#xff0c;一位工作了十年的"技术混子"&#xff0c; 致力于为开发者赋能的UP主, 目前正在运营着 TFS_CLUB社区。 &#x1f4ac; 人生格言&#xff1a;优于别人,并不高贵,真正的高贵应该是优于过去的自己。&#x1f4ac; &#x1f4e…

如何利用github搭建个人主页网站?

本章教程告诉你如何利用github搭建一个个人静态主页网站。 适合没有服务器和域名且对网站搭建感兴趣的人玩玩&#xff0c;github稳定性可能差一点。 目录 一、前期准备工作 二、 创建项目仓库 三、将网站上传到github 四、我的个人主页展示 一、前期准备工作 1、首先&#x…

[1.1_1]计算机系统概述——操作系统的概念、功能和目标

文章目录第一章 计算机系统概述操作系统的概念&#xff08;定义&#xff09;、功能和目标&#xff08;一&#xff09;操作系统的概念&#xff08;定义&#xff09;&#xff08;二&#xff09;操作系统的功能和目标1、作为系统资源的管理者2、向上层提供方便易用的服务3、作为最…

选课系统的设计与实现

技术&#xff1a;Java等摘要&#xff1a;目前国内各高校的规模越来越大&#xff0c;进而造成教师教学管理等工作量日趋加大。然而&#xff0c;现代教育的信息化、网络化已经成为教育发展的一个重要方向&#xff0c;同时也为解决高校教学管理效率低下的现状&#xff0c;使管理突…

[架构之路-126]-《软考-系统架构设计师》-操作系统-5-虚拟化技术、Docker与虚拟机比较

第1章 Docker与虚拟机比较总体概述1.1 宏观比较虚拟机和Docker容器技术都是一种虚拟化技术。虚拟机包含的是整个操作系统的原生镜像&#xff0c;非常的庞大。docker的镜像只包含最核心的环境&#xff0c;非常小巧。&#xff08;1&#xff09;比较Docker与虚拟机技术的不同&…

【CS224W】(task9)图神经网络的表示能力(更新中!!)

note 基于图同构网络&#xff08;GIN&#xff09;的图表征网络。为了得到图表征首先需要做节点表征&#xff0c;然后做图读出。GIN中节点表征的计算遵循WL Test算法中节点标签的更新方法&#xff0c;因此它的上界是WL Test算法。 在图读出中&#xff0c;我们对所有的节点表征&…

线程基础复习

线程基础复习 程序&#xff1a;一段静态的代码 进程&#xff1a;正在执行的程序,是操作系统资源分配的最小单位 线程&#xff1a;进程可进一步细分为线程,是进程内部最小的执行单元,是操作系统进行任务调度的最小单元,属于进程 线程与进程的关系 一个进程可以包含多个线程,…