当前位置: 首页 > article >正文

Spring-容器:IOC-基于注解管理Bean

目录

  • 一、基于注解管理Bean(重点)
    • 1.1、概述
    • 1.2、开启组件扫描
      • 1.2.1、指定要排除的组件
      • 1.2.2、仅扫描指定组件
    • 1.3、使用注解定义Bean
    • 1.4、使用@Autowired注入
      • 1.4.1、属性注入
      • 1.4.2、set注入
      • 1.4.3、构造方法注入
      • 1.4.4、形参注入
      • 1.4.5、无注解注入
      • 1.4.6、联合@Qualifier注解注入
    • 1.5、使用@Resource注入
      • 1.5.1、Name注入
      • 1.5.2、未知Name注入
      • 1.5.3、类型注入
    • 1.6、全注解开发

一、基于注解管理Bean(重点)

1.1、概述

简介

​ 从 Java 5 开始,Java 增加了对注解(Annotation)的支持,它是代码中的一种特殊标记,可以在编译、类加载和运行时被读取,执行相应的处理。开发人员可以通过注解在不改变原有代码和逻辑的情况下,在源代码中嵌入补充信息。

​ Spring 从 2.5 版本开始提供了对注解技术的全面支持,我们可以使用注解来实现自动装配,简化 Spring 的 XML 配置。

步骤

  1. 引入依赖
  2. 开启组件扫描
  3. 使用注解定义 Bean
  4. 依赖注入

使用注解

Spring 提供了以下多个注解,这些注解可以直接标注在 Java 类上,将它们定义成 Spring Bean

在这里插入图片描述

1.2、开启组件扫描

概述

​ Spring 默认不支持注解装配 Bean,因此我们需要在 Spring 的 XML 配置中,通过 context:component-scan 元素开启 Spring Beans的自动扫描功能。开启此功能后,Spring 会自动从扫描指定的包(base-package 属性设置)及其子包下的所有类,如果类上使用了 @Component 注解,就将该类装配到容器中。

  • 步骤一:添加约束

    <?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-3.0.xsd
        http://www.springframework.org/schema/context
                http://www.springframework.org/schema/context/spring-context.xsd">
    </beans>
    
  • 步骤二:开启扫描方式

    <context:component-scan base-package="com.atguigu.spring6">
    </context:component-scan>
    

1.2.1、指定要排除的组件

<context:exclude-filter></context:exclude-filter>标签,指定排除规则

  • type属性:设置排除或包含的依据
    • annotation,根据注解排除
    • assignable,根据类型排除
  • expression属性:设置要排除的注解或类型的全类名
<context:component-scan base-package="com.atguigu.spring6">
    <!-- context:exclude-filter标签:指定排除规则 -->
    <!-- 
 		type:设置排除或包含的依据
		type="annotation",根据注解排除,expression中设置要排除的注解的全类名
		type="assignable",根据类型排除,expression中设置要排除的类型的全类名
	-->
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        <!--<context:exclude-filter type="assignable" expression="com.atguigu.spring6.controller.UserController"/>-->
</context:component-scan>

1.2.2、仅扫描指定组件

  • use-default-filters="false",表示关闭默认扫描规则
  • <context:include-filter></context:include-filter>,表示指定的过滤条件来确定哪些类应该被包含在组件扫描中
<context:component-scan base-package="com.atguigu" use-default-filters="false">
    <!-- context:include-filter标签:指定在原有扫描规则的基础上追加的规则 -->
    <!-- use-default-filters属性:取值false表示关闭默认扫描规则 -->
    <!-- 此时必须设置use-default-filters="false",因为默认规则即扫描指定包下所有类 -->
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    <!--<context:include-filter type="assignable" expression="com.atguigu.spring6.controller.UserController"/>-->
</context:component-scan>

1.3、使用注解定义Bean

Spring 提供了以下多个注解,这些注解可以直接标注在 Java 类上,将它们定义成 Spring Bean
在这里插入图片描述

1.4、使用@Autowired注入

单独使用@Autowired注解时,默认是根据类型装配

  • @Autowired注解可以标注在:构造方法上、方法上、形参上、属性上、注解上
  • @Autowired注解的required属性,
    • 属性值为True:表示注入的时候要求被注入的Bean必须是存在的,如果不存在则报错
    • 属性值为False::表示注入的时候要求被注入的Bean不一定是存在的,如果存在的话就注入,不存在的话,也不报错

1.4.1、属性注入

在这里插入图片描述
当使用@Autowired注解注入时,可不提供构造方法喝Setter方法,也可以注入成功

1.创建UserDao接口

package com.atguigu.spring6.dao;
public interface UserDao {
    public void print();
}

2.创建UserDaoImpl实现

package com.atguigu.spring6.dao.impl;
import com.atguigu.spring6.dao.UserDao;
import org.springframework.stereotype.Repository;
@Repository
public class UserDaoImpl implements UserDao {
    @Override
    public void print() {
        System.out.println("Dao层执行结束");
    }
}

3.创建UserService接口

package com.atguigu.spring6.service;
public interface UserService {
    public void out();
}

4.创建UserServiceImpl实现类

package com.atguigu.spring6.service.impl;
import com.atguigu.spring6.dao.UserDao;
import com.atguigu.spring6.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements UserService {
    //注入dao
    //属性注入
    @Autowired//根据类型找到对应对象,完成注入
    private UserDao userDao;

    @Override
    public void out() {
        userDao.print();
        System.out.println("Service层执行结束");
    }
}

5.创建UserController类

package com.atguigu.spring6.controller;
import com.atguigu.spring6.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class UserController {
    //注入service
    //属性注入
    @Autowired//根据类型找到对应对象,完成注入
    private UserService userService;

    public void out() {
        userService.out();
        System.out.println("Controller层执行结束。");
    }
}

步骤二:演示

@Test
public void testAnnotation(){
    ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
    UserController userController = context.getBean("userController", UserController.class);
    userController.out();
}

1.4.2、set注入

1.修改UserServiceImpl类

@Service
public class UserServiceImpl implements UserService {
    private UserDao userDao;
    @Autowired//set方法注入
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    @Override
    public void out() {
        userDao.print();
        System.out.println("Service层执行结束");
    }
}

2.修改UserController类

@Controller
public class UserController {
    private UserService userService;

    @Autowired//set方法注入
    public void setUserService(UserService userService) {
        this.userService = userService;
    }
    public void out() {
        userService.out();
        System.out.println("Controller层执行结束。");
    }
}

1.4.3、构造方法注入

1.修改UserServiceImpl类

@Service
public class UserServiceImpl implements UserService {
    private UserDao userDao;
    @Autowired
    public UserServiceImpl(UserDao userDao) {
        this.userDao = userDao;
    }
    @Override
    public void out() {
        userDao.print();
        System.out.println("Service层执行结束");
    }
}

2.修改UserController类

@Controller
public class UserController {
    private UserService userService;
    @Autowired
    public UserController(UserService userService) {
        this.userService = userService;
    }
    public void out() {
        userService.out();
        System.out.println("Controller层执行结束。");
    }

}

1.4.4、形参注入

1.修改UserServiceImpl类

@Service
public class UserServiceImpl implements UserService {

    private UserDao userDao;

    public UserServiceImpl(@Autowired UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public void out() {
        userDao.print();
        System.out.println("Service层执行结束");
    }
}

2.修改UserController类

@Controller
public class UserController {

    private UserService userService;

    public UserController(@Autowired UserService userService) {
        this.userService = userService;
    }

    public void out() {
        userService.out();
        System.out.println("Controller层执行结束。");
    }
}

1.4.5、无注解注入

当有参数的构造方法只有一个时,@Autowired注解可以省略
1.修改UserServiceImpl类

@Service
public class UserServiceImpl implements UserService {

 
    private UserDao userDao;

    public UserServiceImpl(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public void out() {
        userDao.print();
        System.out.println("Service层执行结束");
    }
}

1.4.6、联合@Qualifier注解注入

当需要注入的接口有多个实现类时,可以联合使用@Qualifier(“userDaoImpl”) 注解,并指定实现类的名字,即可完成属性注入
1.添加UserDaoRedisImpl类

@Repository
public class UserDaoRedisImpl implements UserDao {

    @Override
    public void print() {
        System.out.println("Redis Dao层执行结束");
    }
}

说明:

  • 此时,添加实现UserDao接口类,已经造成一个接口对应两个实现类
  • 此时,程序错误,信息中说:不能装配,UserDao这个Bean的数量等于2

步骤二:修改UserServiceImpl类

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    @Qualifier("userDaoImpl") // 指定bean的名字
    private UserDao userDao;

    @Override
    public void out() {
        userDao.print();
        System.out.println("Service层执行结束");
    }
}

1.5、使用@Resource注入

@Resource注解是通过名称匹配的方式来实现注入的,默认按照名称进行匹配,未指定名称,使用属性名作为name,如果找不到匹配的名称,则会尝试按照类型匹配

用在属性上、set方法上

如果是JDK8的话不需要额外引入依赖。高于JDK11或低于JDK8需要引入以下依赖

<dependency>
    <groupId>jakarta.annotation</groupId>
    <artifactId>jakarta.annotation-api</artifactId>
    <version>2.1.1</version>
</dependency>

1.5.1、Name注入

1.修改UserDaoImpl类

package com.atguigu.spring6.dao.impl;

import com.atguigu.spring6.dao.UserDao;
import org.springframework.stereotype.Repository;

@Repository("myUserDao")
public class UserDaoImpl implements UserDao {

    @Override
    public void print() {
        System.out.println("Dao层执行结束");
    }
}

当使用注解时,在小括号内写上属性名称表示为此Bean定义别名

2.修改UserServiceImpl类

package com.atguigu.spring6.service.impl;

import com.atguigu.spring6.dao.UserDao;
import com.atguigu.spring6.service.UserService;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService {

    @Resource(name = "myUserDao")
    private UserDao myUserDao;

    @Override
    public void out() {
        myUserDao.print();
        System.out.println("Service层执行结束");
    }
}

当使用@Resource注解时,可以使用name属性指定属性注入的别名

1.5.2、未知Name注入

1.修改UserDaoImpl类

package com.atguigu.spring6.dao.impl;

import com.atguigu.spring6.dao.UserDao;
import org.springframework.stereotype.Repository;

@Repository("myUserDao")
public class UserDaoImpl implements UserDao {

    @Override
    public void print() {
        System.out.println("Dao层执行结束");
    }
}

2.修改UserServiceImpl类

package com.atguigu.spring6.service.impl;

import com.atguigu.spring6.dao.UserDao;
import com.atguigu.spring6.service.UserService;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService {

    @Resource
    private UserDao myUserDao;

    @Override
    public void out() {
        myUserDao.print();
        System.out.println("Service层执行结束");
    }
}

当使用@Resource注解时,在name属性未知的情况下,将属性注入的成员属性变量名定义为与Bean同名,即可完成注入

1.5.3、类型注入

1.原UserDaoImpl类

@Repository("myUserDao")
public class UserDaoImpl implements UserDao {

    @Override
    public void print() {
        System.out.println("Dao层执行结束");
    }
}

2.修改UserServiceImpl类

@Service
public class UserServiceImpl implements UserService {

    @Resource
    private UserDao userDao1;

    @Override
    public void out() {
        userDao1.print();
        System.out.println("Service层执行结束");
    }
}

当使用@Resource注解时,现在userDao1属性名不存在,但仍然可以注入成功。因为,UserDao他们的类型名相同

1.6、全注解开发

​ 全注解开发就是不再使用spring配置文件了,写一个配置类来代替配置文件

使用@ComponentScan注解,进行组件扫描,从而替代了原有在xml文件中的配置

步骤一:创建配置类

@Configuration
//@ComponentScan({"com.atguigu.spring6.controller", "com.atguigu.spring6.service","com.atguigu.spring6.dao"})
@ComponentScan("com.atguigu.spring6")
public class Spring6Config {
}

步骤二:演示

​ 需要使用AnnotationConfigApplicationContext类来获取Spring6Config的字节码文件

@Test
public void testAllAnnotation(){
    ApplicationContext context = new AnnotationConfigApplicationContext(Spring6Config.class);
    UserController userController = context.getBean("userController", UserController.class);
    userController.out();
    logger.info("执行成功");
}


http://www.kler.cn/news/294608.html

相关文章:

  • C++11 --- 智能指针
  • 自然语言处理系列五十》文本分类算法》SVM支持向量机算法原理
  • 超详细!!!electron-vite-vue开发桌面应用之创建新窗口以及主进程和子进程的通信监听(十二)
  • (1)DRF项目服务器部署(Linux/Nginx/Uwsgi)
  • 数据结构---双向链表(内存泄露相关知识)
  • 关于易优cms自定义字段不显示的问题
  • 梧桐数据库(WuTongDB):聚簇索引的原理、实现方法及应用场景
  • [RK3588][Android12] Android->拦截指定进程冻结,避免后台服务长时间运行被系统冻结
  • Spring全局异常处理HandlerExceptionResolver使用
  • 【网络安全基础】网络安全的基本概念与威胁
  • Python批量提取pdf标题-作者信息
  • Redis发布订阅PUB/SUB
  • 04使用python处理交通时空大数据
  • 初识Linux · 进度条
  • K8S 发布应用
  • 【60天备战软考高级系统架构设计师——第十一天:系统集成与测试——集成策略】
  • kafka集群安装
  • OpenFeign的使用(一)
  • 软件测试之UI自动化测试
  • nginx配置中的服务器名称
  • 家政上门小程序系统设计解析
  • C#语言实现最小二乘法算法
  • 怎么强制撤销excel工作表保护?
  • 深度学习从入门到精通——yolov1
  • F12抓包06-1:浏览器导出postman测试脚本
  • sicp每日一题[2.1]
  • docker 容器
  • 数据库 | 子查询 | sql执行顺序 | mysql是否运行
  • AI文献综述神器,有这一款就够了!
  • 《JavaEE进阶》----11.<SpringIOCDI【Spring容器+IOC详解+DI介绍】>