基于注解配置bean

news2024/11/17 13:48:49

文章目录

    • 1.基本使用
        • 1.基本介绍
        • 2.快速入门
          • 1.引入jar包
          • 2.MyComponent.java
          • 3.UserAction.java
          • 3.UserDao.java
          • 4.UserService.java
          • 5.beans05.xml
          • 6.断点查看bean对象是否创建
          • 7.测试
        • 3.注意事项和细节
    • 2.自己实现spring注解
        • 1.需求分析
        • 2.思路分析图
        • 3.编写自定义注解ComponentScan
        • 4.编写配置类SunSpringConfig
        • 5.编写容器SunSpringApplicationContext
        • 6.测试
    • 3.自动装配
        • 1.AutoWired方式
          • 1.基本说明
          • 2.UserDao.java
          • 3.UserService.java
          • 4.测试
        • 2.Resource方式(推荐)
          • 1.基本说明
          • 2.UserDao.java
          • 3.UserService.java
    • 4.泛型依赖注入
        • 1.基本说明
          • 1.基本介绍
          • 2.参考关系图

1.基本使用

1.基本介绍

image-20240219101916177

2.快速入门
1.引入jar包

image-20240219102154951

2.MyComponent.java
package com.sxs.spring.component;

import org.springframework.stereotype.Component;

/**
 * @Component 标识该类是一个组件,当不确定该类的层级的时候就使用这个注解
 * @author 孙显圣
 * @version 1.0
 */

@Component
public class MyComponent {
}

3.UserAction.java
package com.sxs.spring.component;

import org.springframework.stereotype.Controller;

/**
 * @Controller 用于标识该类是一个控制器(相当于servlet)
 * @author 孙显圣
 * @version 1.0
 */
@Controller
public class UserAction {
}

3.UserDao.java
package com.sxs.spring.component;

import org.springframework.stereotype.Repository;

/**
 * @Repository 用来标识该类是一个dao
 * @author 孙显圣
 * @version 1.0
 */
@Repository
public class UserDao {
}

4.UserService.java
package com.sxs.spring.component;

import org.springframework.stereotype.Service;

/**
 * @Service 用于标识该类是一个Service
 * @author 孙显圣
 * @version 1.0
 */
@Service
public class UserService {
}

5.beans05.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">
    <!--
        component-scan 表示对指定包下的类进行扫描,并创建对象到容器
        base-package 指定要扫描的包
    -->
    <context:component-scan base-package="com.sxs.spring.component"></context:component-scan>
</beans>
6.断点查看bean对象是否创建

image-20240219104840942

7.测试
    //通过注解来配置bean
    @Test
    public void setBeanByAnnotation() {
        //从类路径下读取配置文件
        ApplicationContext ioc = new ClassPathXmlApplicationContext("beans05.xml");
        //分别获取这四个对象,由于是单例的所以可以直接通过类型获取
        MyComponent component = ioc.getBean(MyComponent.class);
        UserAction action = ioc.getBean(UserAction.class);
        UserDao userDao = ioc.getBean(UserDao.class);
        UserService userService = ioc.getBean(UserService.class);
        System.out.println("" + component + action + userDao + userService);
    }

image-20240219105551384

3.注意事项和细节

image-20240219105946438

image-20240219133850259

image-20240219133918902

image-20240219134100805

image-20240219134942963

2.自己实现spring注解

1.需求分析

image-20240219135303466

image-20240219135325093

2.思路分析图

image-20240219140946226

3.编写自定义注解ComponentScan
package com.sxs.spring.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 自定义注解:用于指定要扫描的包
 *
 * @author 孙显圣
 * @version 1.0
 */
@Target(ElementType.TYPE) //指定目前的注解可以修饰TYPE程序元素
@Retention(RetentionPolicy.RUNTIME) //指定注解的保留范围,在运行时可以生效
public @interface ComponentScan {
    String value() default ""; //指定注解可以传入一个String类型的值,用于指定要扫描的包
}

4.编写配置类SunSpringConfig
package com.sxs.spring.annotation;

/**
 * @author 孙显圣
 * @version 1.0
 */
@ComponentScan(value = "com.sxs.spring.component") //自定义注解:指定要扫描的包
public class SunSpringConfig {

}

5.编写容器SunSpringApplicationContext
package com.sxs.spring.annotation;

import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.File;
import java.net.URL;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 类似于Spring原生的ioc容器
 *
 * @author 孙显圣
 * @version 1.0
 */
public class SunSpringApplicationContext {
    //传进来一个配置类的Class对象
    private Class configClass;
    //存放对象的容器
    private final ConcurrentHashMap<String, Object> ioc = new ConcurrentHashMap<>();
    //构造器,接收配置类的class对象
    public SunSpringApplicationContext(Class configClass) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        this.configClass = configClass;
        //获取要扫描的包
        //1.首先反射获取类的注解信息
        ComponentScan componentScan = (ComponentScan) this.configClass.getDeclaredAnnotation(ComponentScan.class);
        //2.通过注解来获取要扫描的包的路径
        String path = componentScan.value();

        //得到要扫描包的.class文件
        //1.获取类加载器
        ClassLoader classLoader = SunSpringApplicationContext.class.getClassLoader();
        //2.获取要扫描包的真实路径,默认刚开始在根目录下
        path = path.replace(".", "/");
        URL resource = classLoader.getResource(path);
        //3.由该路径创建一个文件对象,可使用resource.getFile()将URL类型转化为String类型
        File file = new File(resource.getFile());
        //4.遍历该文件夹下的所有.class文件
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            for (File f : files ) {
                //反射注入容器
                //1.获取所有文件的全路径
                String absolutePath = f.getAbsolutePath();
                //只处理class文件
                if (absolutePath.endsWith(".class")) {
                    //2.分割出类名
                    String className = absolutePath.substring(absolutePath.lastIndexOf("\\") + 1, absolutePath.indexOf("."));
                    //3.得到全路径
                    String fullPath = path.replace("/", ".") + "." + className;
                    //4.类加载器获取Class对象(也可以通过Class.forName,区别是后者会使类被静态初始化),判断是否有那四个注解
                    Class<?> aClass = classLoader.loadClass(fullPath);
                    if (aClass.isAnnotationPresent(Component.class) || aClass.isAnnotationPresent(Controller.class)
                    || aClass.isAnnotationPresent(Service.class) || aClass.isAnnotationPresent(Repository.class)) {
                        //5.反射对象并放入到容器中
                        Class<?> clazz = Class.forName(fullPath);
                        Object o = clazz.newInstance();
                        //默认是类名首字母小写作为key
                        ioc.put(StringUtils.uncapitalize(className), o);
                    }
                }
            }
            System.out.println("ok");
        }
    }

    //返回容器中的对象
    public Object getBean(String name) {
        return ioc.get(name);
    }

}

6.测试
package com.sxs.spring.annotation;

import org.junit.jupiter.api.Test;

/**
 * @author 孙显圣
 * @version 1.0
 */
public class test {
    @Test
    public void SunSpringApplicationContextTest() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        SunSpringApplicationContext ioc = new SunSpringApplicationContext(SunSpringConfig.class);
        Object myComponent = ioc.getBean("myComponent");
        Object userAction = ioc.getBean("userAction");
        Object userDao = ioc.getBean("userDao");
        Object userService = ioc.getBean("userService");
        System.out.println("" + myComponent + userService + userAction + userDao);
    }
}

image-20240219160545576

3.自动装配

1.AutoWired方式
1.基本说明

image-20240219172851649

2.UserDao.java
package com.sxs.spring.component;

import org.springframework.stereotype.Repository;

/**
 * @Repository 用来标识该类是一个dao
 * @author 孙显圣
 * @version 1.0
 */
@Repository
public class UserDao {
    public void sayHi() {
        System.out.println("hi");
    }
}

3.UserService.java
package com.sxs.spring.component;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @Service 用于标识该类是一个Service
 * @author 孙显圣
 * @version 1.0
 */
@Service
public class UserService {
    //自动装配
    //1.通过UserDao这个类型来匹配,如果有多个实例,则使用第二种方式匹配
    //2.通过userDao这个属性名字作为id匹配实例,如果还是匹配不到则报错
    @Autowired
    UserDao userDao;

    public void sayHi() {
        userDao.sayHi();
    }
}

4.测试
    //测试@autowire自动装配
    @Test
    public void autowireTest() {
        //获取容器
        ApplicationContext ioc = new ClassPathXmlApplicationContext("beans05.xml");
        UserService bean = ioc.getBean("userService", UserService.class);
        bean.sayHi();
    }

image-20240219173043506

2.Resource方式(推荐)
1.基本说明

image-20240219173244707

2.UserDao.java
package com.sxs.spring.component;

import org.springframework.stereotype.Repository;

/**
 * @Repository 用来标识该类是一个dao
 * @author 孙显圣
 * @version 1.0
 */
@Repository
public class UserDao {
    public void sayHi() {
        System.out.println("hi");
    }
}

3.UserService.java
package com.sxs.spring.component;

import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * @Service 用于标识该类是一个Service
 * @author 孙显圣
 * @version 1.0
 */
@Service
public class UserService {
    //自动装配
    //1.通过name匹配:直接根据注解的属性name来进行匹配,如果匹配不到直接报错
    //2.通过类型匹配:必须保证是单例的,如果有多个实例,则直接报错
    //3.默认:先通过name属性匹配,如果匹配不上则按照类型匹配,都匹配不上才会报错
    @Resource
    UserDao userDao;

    public void sayHi() {
        userDao.sayHi();
    }
}

4.泛型依赖注入

1.基本说明
1.基本介绍

image-20240219184142629

2.参考关系图

image-20240219185501222

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

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

相关文章

【Linux 杂货铺】进程间通信

1.进程为什么要通信呢&#xff1f; ①&#x1f34e; 为了进程之间更好的协同工作&#xff0c;举个例子&#xff0c;在学校&#xff0c;学院的管理人员给教师安排课程的时候&#xff0c;必须事先知道该教师平常的上课情况&#xff0c;不然会将教师的课程安排到一起造成麻烦&…

皇后之战:揭秘N皇后问题的多维解法与智慧【python 力扣52题】

作者介绍&#xff1a;10年大厂数据\经营分析经验&#xff0c;现任大厂数据部门负责人。 会一些的技术&#xff1a;数据分析、算法、SQL、大数据相关、python 欢迎加入社区&#xff1a;码上找工作 作者专栏每日更新&#xff1a; LeetCode解锁1000题: 打怪升级之旅 python数据分析…

(2022级)成都工业学院数据库原理及应用实验六: SQL DML(增、删、改)

写在前面 1、基于2022级软件工程/计算机科学与技术实验指导书 2、成品仅提供参考 3、如果成品不满足你的要求&#xff0c;请寻求其他的途径 运行环境 window11家庭版 Navicat Premium 16 Mysql 8.0.36 实验要求 在实验三的基础上完成下列查询&#xff1a; 1、在科室表…

【在线OJ系统】自定义注解实现分布式ID无感自增

实现思路 首先自定义参数注解&#xff0c;然后根据AOP思想&#xff0c;找到该注解作用的切点&#xff0c;也就是mapper层对于mapper层的接口在执行前都会执行该aop操作&#xff1a;获取到对于的方法对象&#xff0c;根据方法对象获取参数列表&#xff0c;根据参数列表判断某个…

大厂面试精华面试刷题

1.自定义unshift实现相同效果 2.数组去重 用vs2019来写这种练习题可以更直观的查看代码执行的效果&#xff0c;最后的代码是控制控制台执行完毕后不自动关闭 use strict;let arr [1, 1, 2, 2, 3, 3, 4, 5, 6, 7, 8, 9, 10] //1.//查重最简单的方法for循环结合splice从数组中…

新版a_bogus算法分析以及成品展示调用

新版a_bogus算法的过程&#xff0c;仅学习参考&#xff0c;如有涉及侵权联系本人删除 最近看到这个参数花了点时间研究了一下 流程和X-Bogus差不多&#xff0c;通过对这段字符串概是对数据、ua、时间戳、浏览器的几个指纹进行计算&#xff0c;长度168位 下面是实现效果以及测…

java解决常见递归问题

最基本的&#xff0c;斐波那契数列&#xff0c;阶乘&#xff08;0&#xff0c;1的阶乘均为1&#xff09; 返回字母“x”第一次出现的位置 使用递归编写一个函数&#xff0c;读取一个字符串&#xff0c;返回字母“x”第一次出现的位置。例如&#xff0c;字符串 "abcdefgh…

Vue3+antd:表格中合并多行相同数据

注&#xff1a;本次以合并相同ID为示例 首先获取远程数据&#xff0c;获取完成之后对数据进行遍历 let customCellList []; // {start:0,length:2,id:xx} // 如果接口返回的数据相同ID之间不相邻&#xff0c;需要手动排序后才可以实现合并效果 res.data.forEach((item, inde…

使用共振峰提取元音音素/从声音生成口型动画

视频效果 我前段时间研究了下从声音提取共振峰的方法。今天测试了下实际效果。 我使用一段33秒的女声视频&#xff0c;提取元音后使用静态视位图序列生成了一个视频&#xff0c;效果如下&#xff1a; b站视频&#xff1a; https://www.bilibili.com/video/BV1JD421H7m9/?vd_…

基于SpringBoot+Vue的体检管理系统 免费获取源码

项目源码获取方式放在文章末尾处 项目技术 数据库&#xff1a;Mysql5.7/8.0 数据表&#xff1a;12张 开发语言&#xff1a;Java(jdk1.8) 开发工具&#xff1a;idea 前端技术&#xff1a;vue html 后端技术&#xff1a;SpringBoot 功能简介 (有文档) 项目获取关键字&…

Springboot+Vue项目-基于Java+MySQL的网上超市系统(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &…

【Redis】string数据类型

文章目录 常用命令setsetnx & NXXXsetex & EXpsetex & PX msetget & mgetincr & decrincrby & decrbyincrbyfloatappendgetrangesetrangestrlen 内部编码 字符串类型是 Redis 最基础的数据类型。 在redis中所有的键都是 string 类型&#xff0c;其他的…

[大模型]Qwen-Audio-chat FastApi 部署调用

Qwen-Audio-chat FastApi 部署调用 Qwen-Audio 介绍 Qwen-Audio 是阿里云研发的大规模音频语言模型&#xff08;Large Audio Language Model&#xff09;。Qwen-Audio 可以以多种音频 (包括说话人语音、自然音、音乐、歌声&#xff09;和文本作为输入&#xff0c;并以文本作为…

改进前后端交互实例

前后端交互实例(javaweb05)-CSDN博客 在这之前我假设大家都已经学完了IOC和DI 不明白的这里我也解释一下,首先是两个概念 1.控制反转:对象的创建控制权由程序自身转到外部(容器) 2.依赖注入:容器为程序提供运行时所依赖的资源 Bean对象:IOC容器中创建,关联的对象,称之为be…

蓝桥杯第十五界软件测试线下省赛题目分析及解决

PS 需要第十五界蓝桥杯被测系统或者功能测试模板、单元测试被测代码、自动化测试被测代码请加&#x1f427;:1940787338 备注&#xff1a;15界蓝桥杯省赛软件测试 题目1&#xff1a;功能测试 题目描述 ​ 某物流公司的货运收费标准根据重量、距离和节假日三个因素来确定。如…

MATLAB 体素滤波(62)

MATLAB 体素滤波(62) 一、算法介绍二、算法实现1.代码(已验证,直接运行)一、算法介绍 这里的代码完成文件读入,体素滤波,效果显示,结果输出的操作,下面是效果截图,后面是代码。 体素滤波(Voxel Filtering)是一种用于三维点云数据处理的方法,其原理类似于二维图像…

linux提权——提权大赏

文章目录 一、可读shadow文件利用提权二、可写shadow文件利用提权三、可写passwd文件利用提权四、sudo环境变量提权配置环境实验 五、自动任务文件权限提升配置环境实验 六、自动任务PATH环境变量提权七、自动任务通配符提权 一、可读shadow文件利用提权 ls -al /etc/shadow #…

JUC面试——⭐⭐Java中的四种引用类型/Threadlocal

四种引用类型 Java 中对象的引用分为四种级别&#xff0c;这四种级别由高到低依次为&#xff1a;强引用、软引用、弱引用和虚引用。 基础知识 强引用&#xff1a;普通使用的引用 强引用是造成 Java 内存泄漏的主要原因之一 软引用&#xff1a; GC内存不够时回收 适用于&…

RK3588 linux 修改ulimit 配置

前言 ulimit 主要是用来限制进程对资源的使用情况的&#xff0c;它支持各种类型的限制&#xff0c;常用的有&#xff1a; 内核文件的大小限制进程数据块的大小限制Shell进程创建文件大小限制可加锁内存大小限制常驻内存集的大小限制打开文件句柄数限制分配堆栈的最大大小限制C…

椋鸟数据结构笔记#10:排序·中

文章目录 四、归并排序时间复杂度实现递归实现非递归实现 测试稳定性 五、非比较排序5.1 计数排序时间复杂度实现测试局限性 5.2 桶排序时间复杂度实现测试 5.3 基数排序时间复杂度实现测试局限性 萌新的学习笔记&#xff0c;写错了恳请斧正。 四、归并排序 归并排序是一种非常…