简易Spring IOC实现

手动实现简易Spring IOC容器.zip 本文还有配套的精品资源,点击获取 简介:本课程致力于从零开始指导开发者手动构建一个依赖注入(DI)容器,这是理解Spring框架核心的重要步骤。通过反向控制(IoC)原理,实现对象的实例化、组装和管理,从而降低组件耦合度。构建过程涉及定义Bean、配置元数据、解析元数据、实现Bean工厂、依赖注入和接口设计等关键步骤,以及可选的面向切面编程(AOP)支持。教程中包含一个示例... 阅读详情

pom.xml的配置文件如下:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>spring1</groupId>
	<artifactId>test1</artifactId>
	<packaging>war</packaging>
	<version>0.0.1-SNAPSHOT</version>
	<name>test1 Maven Webapp</name>
	<url>http://maven.apache.org</url>
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>

		<!-- requied start -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.4</version>
			<scope>provided</scope>
		</dependency>
		<!-- requied end -->
	</dependencies>
	<build>
		<finalName>test1</finalName>
	</build>
</project>

application.properties的配置如下:

package=com.myTest

代码结构如下:

定义的标签

package com.myTest.spring.Annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * @Target:注解的作用目标
        
        @Target(ElementType.TYPE)   //接口、类、枚举、注解
        @Target(ElementType.FIELD) //字段、枚举的常量
        @Target(ElementType.METHOD) //方法
        @Target(ElementType.PARAMETER) //方法参数
        @Target(ElementType.CONSTRUCTOR)  //构造函数
        @Target(ElementType.LOCAL_VARIABLE)//局部变量
        @Target(ElementType.ANNOTATION_TYPE)//注解
        @Target(ElementType.PACKAGE) ///包   
 * @author an
 *
 */



//作用于 字段、枚举的常量
@Target({ElementType.FIELD})
//注解会在class字节码文件中存在,在运行时可以通过反射获取到
@Retention(RetentionPolicy.RUNTIME)
//说明该注解将被包含在javadoc中
@Documented
public @interface MyAutowired {
	public String value() default "";
}
package com.myTest.spring.Annotation;

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

//作用于 接口、类、枚举、注解
@Target({ElementType.TYPE})
//注解会在class字节码文件中存在,在运行时可以通过反射获取到
@Retention(RetentionPolicy.RUNTIME)
//说明该注解将被包含在javadoc中
@Documented
public @interface MyController {
	public String value() default "";
}

package com.myTest.spring.Annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//作用于接口、类、枚举、注解   和方法
@Target({ElementType.TYPE,ElementType.METHOD})
//注解会在class字节码文件中存在,在运行时可以通过反射获取到
@Retention(RetentionPolicy.RUNTIME)
//说明该注解将被包含在javadoc中
@Documented
public @interface MyRequestMapping {
	public String value() default "";
}

package com.myTest.spring.Annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//方法参数
@Target({ElementType.PARAMETER})
//注解会在class字节码文件中存在,在运行时可以通过反射获取到
@Retention(RetentionPolicy.RUNTIME)
//说明该注解将被包含在javadoc中
@Documented
public @interface MyRequestParam {
	public String value() default "";
}

package com.myTest.spring.Annotation;

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

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyService {
	public String value() default "";
}

DispatchServlet的代码

package com.myTest.spring.Servlet;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.myTest.spring.Annotation.MyAutowired;
import com.myTest.spring.Annotation.MyController;
import com.myTest.spring.Annotation.MyService;

/**
 * 迷你Spring 
 * @author an
 *
 */
public class DispatchServlet extends HttpServlet{

	//加载配置文件
	private Properties contextConfig = new Properties();
	//放置注册的Bean
	private Map<String,Object> beanMap = new ConcurrentHashMap<String, Object>();
	//类的路径
	private List<String> classNames = new ArrayList<String>();


	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {

		doPost(req,resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		System.out.println("----------doPost-----------");
	}

	@Override
	public void init(ServletConfig config) throws ServletException {

		//定位
		doLoadConfig(config.getInitParameter("contextConfigLocation"));
		//加载
		doScanner(contextConfig.getProperty("package"));
		//注册
		doRegister();
		//依赖注入
		doAutowired();

	}



	/**
	 * 依赖注入方法
	 */
	private void doAutowired() {
		if(beanMap.isEmpty()){
			return;
		}
		
		for(Map.Entry<String, Object> entry : beanMap.entrySet()){
			Field[] fields = entry.getValue().getClass().getDeclaredFields();
			
			for(Field f : fields){
				if(!f.isAnnotationPresent(MyAutowired.class)){
					continue;
				}
				MyAutowired myAutowired = f.getAnnotation(MyAutowired.class);
				String beanName = myAutowired.value();
				if("".equals(beanName)){
					beanName = f.getType().getName();
				}
				
				f.setAccessible(true);
				
				try {
					f.set(entry.getValue(), beanMap.get(beanName));
				} catch (Exception e) {
					e.printStackTrace();
				}
				
			}
			
		}
		
	}

	/**
	 * 注册方法
	 */
	private void doRegister() {
		if(classNames.isEmpty()){
			return ;
		}

		try {
			for(String className : classNames){
				Class<?> clazz = Class.forName(className);
				
				if(clazz.isAnnotationPresent(MyController.class)){
					String beanName = lowerFirstWord(clazz.getSimpleName());
					beanMap.put(beanName, clazz.newInstance());
				}else if(clazz.isAnnotationPresent(MyService.class)){
					MyService myService = clazz.getAnnotation(MyService.class);
					
					String beanName = myService.value();
					if("".equals(beanName)){
						beanName = lowerFirstWord(clazz.getSimpleName());
					}
					
					Object instance = clazz.newInstance();
					beanMap.put(beanName, instance);
				}else{
					continue;
				}
				
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}

	}

	/**
	 * 首字母小写
	 * @param simpleName
	 * @return
	 */
	private String lowerFirstWord(String simpleName) {
		char [] chars = simpleName.toCharArray();
		chars[0]+=32;
		return String.valueOf(chars);
	}

	/**
	 * 加载方法
	 * @param property
	 */
	private void doScanner(String property) {
		URL url = this.getClass().getClassLoader().getResource("/"+property.replaceAll("\\.", "/"));
		
		File fileDir = new File(url.getFile());
		
		for(File f : fileDir.listFiles()){
			if(f.isDirectory()){
				doScanner(property+ "." +f.getName());
				System.out.println(property+ "." +f.getName());
			}else{
				classNames.add(property+"."+f.getName().replace(".class", ""));
				//System.out.println(property+"."+f.getName().replace(".class", ""));
			}
		}
	}

	/**
	 * 加载配置文件,获取待扫描的路径
	 * @param location
	 */
	private void doLoadConfig(String location) {
		InputStream is = this.getClass().getClassLoader().getResourceAsStream(location.replace("classpath:", ""));
		
		try {
			contextConfig.load(is);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}





}

渗透测试面试题 渗透测试面试题 一.思路流程 1.信息收集 服务器的相关信息(真实ip,系统类型,版本,开放端口,WAF等) 网站指纹识别(包括,cms,cdn,证书等),dns记录 whois信息,姓名,备案,邮箱,电话反查(邮箱丢社工库,社工准备等) 子域名收集,旁站,C段等 google hacking针对化搜索,pdf文件,中间件版本,弱口令扫描等 扫描网站目录结构,爆后台,网站banner,测试文件,... 阅读详情

相关推荐

保姆级教程:用CANoe手把手复现ECU刷写全流程(含BootLoader三阶段详解)

本文提供了一份详细的CANoe ECU刷写实战指南,涵盖BootLoader三阶段的深度解析。从实验环境搭建到预编程、主编程及后编程阶段,逐步讲解ECU刷写的关键步骤和隐藏逻辑,特别强调UDS诊断和CAN通信的精确控制,帮助开发者掌握ECU刷写的核心技术。

weixin_29234423的博客 531

简单实现spring的IOC

简单实现spring的IOC 当我们熟练使用Spring框架后 发现在项目中最常见的就是注解,那么注解到底是如何在后台运转的? 实际上在框架中我们使用的所有的注解本身都没有任何用处,在框架里边,注解本身只有一个表示的作用(类似于注解),在框架中的注解之所以能实现很多功能,原因是因为每一个注解下面都有大量的反射代码对其进行支持。 IOC 常用的注解如下: @Component @Repository @Service @Controller DI 注解: @Autowried 创建一个maven项目 导入依赖

m0_58016905的博客 270

scDeepCluster_pytorch代码解读与文章理解

论文:Clustering single-cell RNA-seq data with a。

qq_34179307的博客 915

Spring contextConfigLocation默认加载文件的位置

在使用Spring框架的时候,如果我们使用的是XML文件配置Bean的方式的话,我们往往会在web.xml里面配置如下内容: <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/con...

weixin_30711917的博客 327

手机拍照对焦快准狠的秘密:一文看懂PDAF、Dual Pixel和Super PD的区别

本文深入解析手机拍照中的三种主流相位检测自动对焦(PDAF)技术:Shield Pixel、Super PD和Dual Pixel。通过对比它们的原理、优缺点及实际表现,帮助读者理解不同技术的对焦速度、暗光表现和画质影响,从而做出更明智的购机选择。

weixin_26985923的博客 488

淘宝母婴用品数据挖掘及可视化分析研究

1. 背景介绍 在当今的电子商务时代,母婴用品市场已经成为了各大电商平台的一片蓝海。淘宝作为中国最大的电子商务平台,其上的母婴用品交易数据自然引人关注。理解这些数据,可以帮助商家更好地制定营销策略,也可以帮助消费者更好地选择产品。因此,本文将对淘宝母婴用品的数据进行深入的挖掘和分析。 1.1 电子商务的

AI天才研究院 1258

spring的@ContextConfiguration注解

在junit测试的时候,我们需要测试spring的内容时,需要用到@RunWith和@ContextConfiguration两个注解。 在这里介绍下通过注解注入的bean和原生springContext获取到的bean是同一对象。 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"file:src/main/webapp/WEB-INF/applicationContext.xml"}) publi

sdmanooo的专栏 3028

YOLO系列算法改进 | C2PSA改进篇 | 融合FSD频域结构解耦模块 | 双域解耦感知,兼顾全局亮度与局部纹理,适应红外小目标与边缘部署场景 | ICME 2026

YOLO系列算法改进 | C2PSA改进篇 | 融合FSD频域结构解耦模块 | 双域解耦感知,兼顾全局亮度与局部纹理,适应红外小目标与边缘部署场景 | ICME 2026 (以YOLO26最新目标检测模型为基础,利用C2PSA_FSD创新模块进行改进)

2502_91881744的博客 316

Map.Entry与entrySet与entry,getKey()与entry.getValue()的用法

直接上代码 实体类 @Data @AllArgsConstructor @NoArgsConstructor public class SinglePressureResultDTO { private Integer Times; private Integer SCU_number; private Boolean Intervention; private Long startTime_low; private Long low_ti

taiguolaotu的博客 6601

PLSQL Developer安装详细步骤

一、下载安装PLSQL Developer(plsql安装百度也有步骤) 官网下载地址:https://www.allroundautomations.com/registered-plsqldev/ 1、网上自己下载适合自己电脑的安装包(32或64),并解压。 2、打开解压的文件夹,得到以下三个文件(分别是汉化工具,PLSQL安装包、激活码),双击安装,如下图: 3、安装界面,点击next,进入下一步,如图: 4、安装协议界面,此处必须选择“I accept the terms in

Gorden的博客 11万+

17、非线性动力学特征在情感语音与食管语音分析中的应用

本文探讨了非线性动力学特征在情感语音与食管语音分析中的应用。在情感语音识别中,选取Hurst指数、相关维数和Lempel-Ziv复杂度等混沌特征结合统计量,通过神经网络实现了中性、恐惧和愤怒情感的高效分类,全局成功率高达93.78%。在食管语音分析中,针对其缺乏明显周期性的问题,提出基于改进自相关方法的基频测量流程,包括包络计算、平滑与峰值细化,并对基频的物理意义提出思考。研究展示了两类语音在特征表现与技术方法上的差异,展望了其在客服、安全、医疗康复等领域的应用前景,并指出了未来在特征拓展、算法优化和发声机

sunny的博客 77

【SpringMVC】关于classpath和contextConfigLocation

众所周知,基本上javaee的配置文件都放在WEB-INF之下,javaee网页工程默认读取配置文件也只会在这个目录下面读,但经常看到一些javaee不知道是装逼,还是因为用myeclipse自动生成,还是为了好管理的原因,将工程的配置文件移到其它文件夹,他们基本利用了SpringMVC的contextConfigLocation去完成这件事,contextConfigLocation下面常常也伴

编程记录,亲测有效 1万+

复数值神经网络可能是深度学习的未来

复数这种东西,在人的头脑中似乎抽象、似乎复杂,然而,对于计算机来说,一点也不抽象,不复杂,那么,将复数概念推广到神经网络会是什么结果呢?本篇介绍国外的一些同行的尝试实践,请我们注意观察他们的进展。

gongdiwudu的专栏 6619

Spring 手写简易IOC容器

传统方式:开发者像 “手工组装机器”,每个零件(对象)的创建和连接都需亲自处理,一旦某个零件更换,整台机器都需拆解重组。IOC 方式:开发者像 “设计机器图纸”,告诉容器 “需要什么零件” 和 “如何连接”,容器自动组装机器,更换零件时只需修改图纸,机器运行逻辑不变。

2401_89221445的博客 502

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

利用Java的反射 手写简易Spring Ioc容器

利用Java的反射 手写简易Spring Ioc容器,快来试试吧!

Wzp20020903的博客 1515

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

spring6-实现简易版IOC容器

通过自定义注解,实现一个简易版IOC容器,包括其核心功能控制反转和依赖注入

m0_62946761的博客 3207

Spring 框架入门:深入理解 Spring IOC 的实现原理(附手写简易 IOC 容器)

本文深入解析Spring框架的IOC(控制反转)核心机制。首先通过传统编程与IOC的对比,阐述IOC解耦、可配置、可测试的优势。接着介绍Spring的两种IOC容器(BeanFactory和ApplicationContext)及其使用方式。

小二丶的博客 837

java 培训如何用反射做简易 Spring IOC 容器

前言 在学习 Spring 之后,对其中的工作原理产生了浓厚的兴趣,近些日子看视频了解到了一些 SpringIOC 容器的工作原理,并边打边磨做出了一个非常简易的 SpringIOC 容器,实现了他的 XML 文件装配,java 代码装配以及自动装配的功能,下面思路以及代码 一、模仿 XML 形式的装配思路 1.思路 采用 XML 装配 bean 时 Spring 会解析 applicationContext.xml 文件,并将各种类型的 bean 注入 IOC 容器,容器中的 bean 可以被无数

m0_67698950的博客 567

《从零构建一个简易的IOC容器,理解Spring的核心思想》

Spring框架的IOC(控制反转)容器是一个核心概念,它通过将对象的创建和管理从程序员手中转移到容器中,简化了开发流程。IOC容器就像一个智能机器人,能够自动管理和提供所需的Bean对象,而不需要手动创建。使用IOC容器的好处包括减少代码耦合、便于统一管理对象、简化测试和维护。本文通过一个简单的示例,展示了如何从零开始手写一个迷你IOC容器,并通过逐步升级,最终实现一个相对完整的简易IOC容器。通过这个实践,开发者可以更好地理解Spring IOC容器的工作原理及其在Java开发中的重要性。

龚小帅的博客 1073

自制简易Spring IoC容器

什么是IoC 我们知道,Spring主要是由IoC和AOP两个部分组成,这篇文章只讨论IoC。 IoC的中文翻译是“控制反转”,我觉得这个名称特别唬人,看起来好像非常厉害,但是又不知道具体是做什么的。其实用大白话说,IoC容器就是一段用来控制和管理Java中bean对象实例化以及调用的程序。 我们使用IoC容器大体上有两个需求: 其一,使得我们的程序的耦合性降低,当需求发生变更的时候,只需要修改配置文件即可(即尽量少地在原来的程序中做修改)。 其二,每一个类我们只需要其中的一个实例,比如我们的Co

haohulala的博客 852

java培训如何用反射做简易 Spring IOC 容器

前言 在学习Spring之后,对其中的工作原理产生了浓厚的兴趣,近些日子看视频了解到了一些SpringIOC容器的工作原理,并边打边磨做出了一个非常简易的SpringIOC容器,实现了他的XML文件装配,java代码装配以及自动装配的功能,下面思路以及代码 一、模仿XML形式的装配思路 1.思路 采用XML装配bean时Spring会解析applicationContext.xml文件,并将各种类型的bean注入IOC容器,容器中的bean可以被无数次重复调用,极大地提高了系统效率而不用多次重复的n

weixin_45695430的博客 152

自己实现的一个简易Spring框架(IoC+AOP)

IoC和AOP是Spring的核心,可以说没有他们就没有庞大的Spring家族。我也是心血来潮,自己动手写了一个简易的Spring框架。可以通过使用注解来实现IoC容器和AOP。 先说IoC部分吧。源码下载:http://download.youkuaiyun.com/detail/jobsandczj/9841126 IoC 先定义了两个注解@MyBean和@MyAutowired,用来标记Bean和

路漫漫 始于足下 1646

从0开始的Spring IOC简易实现

本文基于Java17实现了一个简易版Spring IOC容器,通过三个核心注解实现依赖注入功能: 主要功能: @MyComponent标记需要自动创建的bean类 @MyAutowired实现属性自动注入 @MyQualifier配合@MyAutowired实现按名称注入 实现要点: 通过类加载器扫描指定包路径下的.class文件 使用反射创建被@MyComponent标记的类实例 维护bean集合和名称映射关系 自动处理依赖注入逻辑,支持按类型和名称匹配

m0_52744273的博客 206

简易版的Spring框架之IOC简单实现

一个简易版的Spring框架 功能 支持singleton类型的bean,包括初始化、属性注入、以及依赖bean注入。 可从xml中读取配置。 可以使用Aspectj的方式进行AOP编写,支持接口和类代理。 说明 如果你有幸能看到 1、本文简易Spring框架参考Github,代码注释参考Github. 2、所有权归原作者,在这里自己只是临摹,参考注释还原过程。不懂的可以看作者的视频。 3、...

weixin_34327223的博客 236

基于Spring IOC实现动态简易版的SPI

基于Java自实现的SPI机制的缺陷,以及使用的复杂性,在实际项目中可以通过Spring IOC来简易的实现一版。 核心做法是: 利用ApplicationContext的getBeansOfType()方法来获取目标接口的全部实现类 需要调用接口的地方, 对外预留属性对应值为接口实现的实际bean_name, 然后根据上面的结果是一个Map, key为接口实现的bean_name, value为接口实现类, 然后通过预留属性获取用户想要使用的具体实现类,属性可以预留默认值,即为系统默认;用户可再进行实现

yichen0429的博客 422

从零手写注解实现简易Spring_IoC容器

本文介绍了一个手动实现简易 Spring IoC 容器的过程。通过分析静态对象创建与动态反射的本质区别,解释了为什么要使用反射而非直接 new 创建对象。文章重点讲解了注解在批量自动扫描类时的筛选作用,并通过四个步骤实现了一个迷你容器:定义自定义注解@MyComponent、编写带注解的业务类、开发核心容器类MyApplicationContext、以及最终测试运行。该容器能自动扫描指定包路径,识别带注解的类并利用反射实例化,存入单例池进行管理。整个过程展示了Spring框架底层注解处理的基本原理,帮助开发

2401_86343364的博客 230
上一篇: 快速排序
下一篇: 二分法查找
欣赏月光
博客等级 码龄12年 63粉丝 66原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值