代码实现SpringIOC与@Resource功能

手写SpringIOC容器框架------@Service和@Resource实现 微信公众号:用心程序员 简介 Spring框架 作为一个轻量级的开源框架不仅给我们的开发工作带来了许多便利,同时也为众多开源框架的研究提供了不可或缺的指导思想。Spring最为核心的两大功能特性就是IOC和AOP.下面主要介绍SpringIOC及自己实现SpringIOC 一、SpringIOC SpringIOC 指的是控制反转,就是把原先我们代码里面需要实现的对象创建、依赖的代码,反转... 阅读详情

本文中将通过自定义的代码实现SpringIOC的XML与注解版本,并且实现@Resource的倚赖注入功能,通过该代码的实现能够更好的理解Spring在该内容的思想原理。

1. 什么是SpringIOC

spring ioc指的是控制反转,IOC容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。交由Spring来管理这些,实现解耦

2. 手写SpringIOCXML版本

实现思路:

  1. 读取配置文件 spring.xml
  2. 使用beanId查找对应的class地址
  3. 使用反射机制初始化对象

由于需要解析xml文件,所以添加dom4j倚赖

   <!-- https://mvnrepository.com/artifact/dom4j/dom4j -->
    <dependency>
      <groupId>dom4j</groupId>
      <artifactId>dom4j</artifactId>
      <version>1.6.1</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/commons-lang/commons-lang -->
    <dependency>
      <groupId>commons-lang</groupId>
      <artifactId>commons-lang</artifactId>
      <version>2.6</version>
    </dependency>
/**
 * XML方式注入bean*
 */
public class MyClassPathXmlApplicationContext {
	// xml路径地址
	private String xmlPath;

	public MyClassPathXmlApplicationContext(String xmlPath) {
		this.xmlPath = xmlPath;
	}

	public Object getBean(String beanId) throws Exception {
		// 1. 读取配置文件
		List<Element> elements = readerXml();
		if (elements == null) {
			throw new Exception("该配置文件没有子元素");
		}
		// 2. 使用beanId查找对应的class地址
		String beanClass = findXmlByIDClass(elements, beanId);
		if (StringUtils.isEmpty(beanClass)) {
			throw new Exception("未找到对应的class地址");
		}
		// 3. 使用反射机制初始化,对象
		Class<?> forName = Class.forName(beanClass);
		return forName.newInstance();
	}

	// 读取配置文件信息
	public List<Element> readerXml() throws DocumentException {
		SAXReader saxReader = new SAXReader();
		if (StringUtils.isEmpty(xmlPath)) {
			new Exception("xml路径为空...");
		}
		Document read = saxReader.read(getClassXmlInputStream(xmlPath));
		// 获取根节点信息
		Element rootElement = read.getRootElement();
		// 获取子节点
		List<Element> elements = rootElement.elements();
		if (elements == null || elements.isEmpty()) {
			return null;
		}
		return elements;
	}

	// 使用beanid查找该Class地址
	public String findXmlByIDClass(List<Element> elements, String beanId) throws Exception {
		for (Element element : elements) {
			// 读取节点上是否有value
			String beanIdValue = element.attributeValue("id");
			if (beanIdValue == null) {
				throw new Exception("使用该beanId未查找到元素");
			}
			if (!beanIdValue.equals(beanId)) {
				continue;
			}
			// 获取Class地址属性
			String classPath = element.attributeValue("class");
			if (!StringUtils.isEmpty(classPath)) {
				return classPath;
			}
		}
		return null;
	}

	// 读取xml配置文件
	public InputStream getClassXmlInputStream(String xmlPath) {
		InputStream resourceAsStream = getClass().getClassLoader().getResourceAsStream(xmlPath);
		return resourceAsStream;
	}

}

spring.xml

<beans>
	<bean id="user" class="org.example.entity.User"></bean>
</beans>

实体类可自行定义

自定义完成后进行测试:

public static void main(String[] args) throws Exception {
	MyClassPathXmlApplicationContext applicationContext = new MyClassPathXmlApplicationContext("spring.xml");
	User user = (User) applicationContext.getBean("user");
	System.out.println(user);//org.example.entity.User@7699a589
}

总结:xml版本逻辑较为简单,仅需传入配置文件路径和beanId即可,使用xml解析技术找到对应的类路径再通过反射进行实例化,而下面的注解版本将会相较复杂些。

3. 手写SpringIOC注解版本与@Resource

实现思路:首先根据包的路径把添加了注解的bean扫描出来,使用反射进行初始化,再将bean存储于容器中。
然后倚赖注入时,遍历所有bean,并判断该bean中的字段是否有添加了@Resource注解,如果有将利用反射机制对该字段进行赋值。

定义注解:

// 自定义注解 注入到Spring容器
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface ExtService {

}
//自定义注解 从Spring容器获取bean
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface ExtResource {

}

可以看出我们要实现的其实就是这两个注解的功能,前者是Spring提供的@service注解,添加该注解能被扫描到Spring的容器中,后者是jdk提供的@resource注解,该注解能以名称注入。

// 手写SpringIOC 注解版本
public class MyClassPathXmlApplicationContext {
	// 扫包的范围
	private String packageName;

	// springbean容器
	private ConcurrentHashMap<String, Object> beans = null;

	public MyClassPathXmlApplicationContext(String packageName) throws Exception {
		beans = new ConcurrentHashMap<>();
		this.packageName = packageName;
		initBeans();
		initEntryField();
	}

	// 初始化属性
	private void initEntryField() throws Exception {
		// 1.遍历所有的bean容器对象
		for (Map.Entry<String, Object> entry : beans.entrySet()) {
			Object bean = entry.getValue();
			// 2.判断属性上面是否有加注解
			attriAssign(bean);
		}

	}

	public Object getBean(String beanId) throws Exception {
		if (StringUtils.isEmpty(beanId)) {
			throw new Exception("beanId参数不能为空");
		}
		// 1.从spring容器获取bean
		Object object = beans.get(beanId);
		// attriAssign(object);
		return object;
	}

	// 初始化对象
	public Object newInstance(Class<?> classInfo)
			throws ClassNotFoundException, InstantiationException, IllegalAccessException {
		return classInfo.newInstance();
	}

	// 初始化对象
	public void initBeans() throws Exception {
		// 1.使用java的反射机制扫包,获取当前包下所有的类
		List<Class<?>> classes = ClassUtil.getClasses(packageName);
		// 2.判断类上是否存在注入bean的注解
		ConcurrentHashMap<String, Object> classExisAnnotation = findClassExisAnnotation(classes);
		if (classExisAnnotation == null || classExisAnnotation.isEmpty()) {
			throw new Exception("该包下没有任何类加上注解");
		}

	}

	// 判断类上是否存在注入bean的注解
	public ConcurrentHashMap<String, Object> findClassExisAnnotation(List<Class<?>> classes) throws Exception {
		for (Class<?> classInfo : classes) {
			// 判断类上是否有注解
			ExtService annotation = classInfo.getAnnotation(ExtService.class);
			if (annotation != null) {
				// 获取当前类名
				String className = classInfo.getSimpleName();
				// 获得beanId,首字母变小写
				String beanId = toLowerCaseFirstOne(className);
				Object newInstance = newInstance(classInfo);
				beans.put(beanId, newInstance);
			}
		}
		return beans;
	}

	// 首字母转小写
	public static String toLowerCaseFirstOne(String s) {
		if (Character.isLowerCase(s.charAt(0)))
			return s;
		else
			return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();
	}

	// 依赖注入注解
	public void attriAssign(Object object) throws Exception {

		// 1.使用反射机制,获取当前类的所有属性
		Class<? extends Object> classInfo = object.getClass();
		Field[] declaredFields = classInfo.getDeclaredFields();

		// 2.判断当前类属性是否存在注解
		for (Field field : declaredFields) {
			ExtResource extResource = field.getAnnotation(ExtResource.class);
			if (extResource != null) {
				// 获取属性名称
				String beanId = field.getName();
				Object bean = getBean(beanId);
				if (bean != null) {
					// 3.默认使用属性名称,查找bean容器对象 1参数 当前对象 2参数给属性赋值
					field.setAccessible(true); // 允许访问私有属性
					field.set(object, bean);
				}

			}
		}

	}

}

其中使用了一个反射工具类,类中的getClasses()方法可以仅传入包名便能遍历出所有的class,如下:

public class ClassUtil {

	/**
	 * 取得某个接口下所有实现这个接口的类
	 */
	public static List<Class> getAllClassByInterface(Class c) {
		List<Class> returnClassList = null;

		if (c.isInterface()) {
			// 获取当前的包名
			String packageName = c.getPackage().getName();
			// 获取当前包下以及子包下所以的类
			List<Class<?>> allClass = getClasses(packageName);
			if (allClass != null) {
				returnClassList = new ArrayList<Class>();
				for (Class classes : allClass) {
					// 判断是否是同一个接口
					if (c.isAssignableFrom(classes)) {
						// 本身不加入进去
						if (!c.equals(classes)) {
							returnClassList.add(classes);
						}
					}
				}
			}
		}

		return returnClassList;
	}

	/*
	 * 取得某一类所在包的所有类名 不含迭代
	 */
	public static String[] getPackageAllClassName(String classLocation, String packageName) {
		// 将packageName分解
		String[] packagePathSplit = packageName.split("[.]");
		String realClassLocation = classLocation;
		int packageLength = packagePathSplit.length;
		for (int i = 0; i < packageLength; i++) {
			realClassLocation = realClassLocation + File.separator + packagePathSplit[i];
		}
		File packeageDir = new File(realClassLocation);
		if (packeageDir.isDirectory()) {
			String[] allClassName = packeageDir.list();
			return allClassName;
		}
		return null;
	}

	/**
	 * 从包package中获取所有的Class
	 * 
	 * @param packageName
	 * @return
	 */
	public static List<Class<?>> getClasses(String packageName) {

		// 第一个class类的集合
		List<Class<?>> classes = new ArrayList<Class<?>>();
		// 是否循环迭代
		boolean recursive = true;
		// 获取包的名字 并进行替换
		String packageDirName = packageName.replace('.', '/');
		// 定义一个枚举的集合 并进行循环来处理这个目录下的things
		Enumeration<URL> dirs;
		try {
			dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
			// 循环迭代下去
			while (dirs.hasMoreElements()) {
				// 获取下一个元素
				URL url = dirs.nextElement();
				// 得到协议的名称
				String protocol = url.getProtocol();
				// 如果是以文件的形式保存在服务器上
				if ("file".equals(protocol)) {
					// 获取包的物理路径
					String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
					// 以文件的方式扫描整个包下的文件 并添加到集合中
					findAndAddClassesInPackageByFile(packageName, filePath, recursive, classes);
				} else if ("jar".equals(protocol)) {
					// 如果是jar包文件
					// 定义一个JarFile
					JarFile jar;
					try {
						// 获取jar
						jar = ((JarURLConnection) url.openConnection()).getJarFile();
						// 从此jar包 得到一个枚举类
						Enumeration<JarEntry> entries = jar.entries();
						// 同样的进行循环迭代
						while (entries.hasMoreElements()) {
							// 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件
							JarEntry entry = entries.nextElement();
							String name = entry.getName();
							// 如果是以/开头的
							if (name.charAt(0) == '/') {
								// 获取后面的字符串
								name = name.substring(1);
							}
							// 如果前半部分和定义的包名相同
							if (name.startsWith(packageDirName)) {
								int idx = name.lastIndexOf('/');
								// 如果以"/"结尾 是一个包
								if (idx != -1) {
									// 获取包名 把"/"替换成"."
									packageName = name.substring(0, idx).replace('/', '.');
								}
								// 如果可以迭代下去 并且是一个包
								if ((idx != -1) || recursive) {
									// 如果是一个.class文件 而且不是目录
									if (name.endsWith(".class") && !entry.isDirectory()) {
										// 去掉后面的".class" 获取真正的类名
										String className = name.substring(packageName.length() + 1, name.length() - 6);
										try {
											// 添加到classes
											classes.add(Class.forName(packageName + '.' + className));
										} catch (ClassNotFoundException e) {
											e.printStackTrace();
										}
									}
								}
							}
						}
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}

		return classes;
	}

	/**
	 * 以文件的形式来获取包下的所有Class
	 * 
	 * @param packageName
	 * @param packagePath
	 * @param recursive
	 * @param classes
	 */
	public static void findAndAddClassesInPackageByFile(String packageName, String packagePath, final boolean recursive,
			List<Class<?>> classes) {
		// 获取此包的目录 建立一个File
		File dir = new File(packagePath);
		// 如果不存在或者 也不是目录就直接返回
		if (!dir.exists() || !dir.isDirectory()) {
			return;
		}
		// 如果存在 就获取包下的所有文件 包括目录
		File[] dirfiles = dir.listFiles(new FileFilter() {
			// 自定义过滤规则 如果可以循环(包含子目录) 或则是以.class结尾的文件(编译好的java类文件)
			public boolean accept(File file) {
				return (recursive && file.isDirectory()) || (file.getName().endsWith(".class"));
			}
		});
		// 循环所有文件
		for (File file : dirfiles) {
			// 如果是目录 则继续扫描
			if (file.isDirectory()) {
				findAndAddClassesInPackageByFile(packageName + "." + file.getName(), file.getAbsolutePath(), recursive,
						classes);
			} else {
				// 如果是java类文件 去掉后面的.class 只留下类名
				String className = file.getName().substring(0, file.getName().length() - 6);
				try {
					// 添加到集合中去
					classes.add(Class.forName(packageName + '.' + className));
				} catch (ClassNotFoundException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

创建好service层:

public interface UserService {
	public void add();
}
//将该类注入到spring容器里面
@ExtService
public class UserServiceImpl implements UserService {
	// 从Spring容器中读取bean
	@ExtResource
	private OrderService orderServiceImpl;

	public void add() {
		orderServiceImpl.addOrder();
		System.out.println("我是使用反射机制运行的方法");
	}
}
public interface OrderService {
	public void addOrder();
}
@ExtService
public class OrderServiceImpl implements OrderService {
	@Override
	public void addOrder() {
		System.out.println("addOrder");
	}
}

进行测试:

public static void main(String[] args) throws Exception {
	ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("org.example.service.impl");
	UserService userService = (UserService) app.getBean("userServiceImpl");
	userService.add();
	System.out.println(userService);
}

在这里插入图片描述
成功注入,大功告成

强化学习入门8—深入理解DDPG 本文是强化学习入门系列的第八篇,前面我们讲Actor-Critic时提到了DDPG。DDPG是google DeepMind团队提出的一种用于输出确定性动作的算法,它解决了Actor-Critic 神经网络每次参数更新前后都存在相关性,导致神经网络只能片面的看待问题这一缺点。同时也解决了DQN不能用于连续性动作的缺点。 阅读详情

相关推荐

金融风控实战:用Python从零搭建贷款违约预测模型(附完整数据集)

本文详细介绍了如何使用Python从零构建金融风控中的贷款违约预测模型,涵盖数据清洗、特征工程、模型构建与评估等全流程。通过实战案例展示逻辑回归、XGBoost和LightGBM三大算法的对比,特别强调AUC-ROC指标在金融风控中的重要性,并附完整数据集和代码实现。

weixin_29175469的博客 237

IOC和DI关系以及autowired与resource的区别

什么是IOC(控制反转)? 控制反转指的就是应用程序把对象的所有控制权都交给Spring容器,应用程序本身不负责对象的创建和维护,然后容器把对象的使用权反转给程序。 实例化对象的两种实现方式: 配置方式: 注解方式: 1.通过扫描方式,扫描指定包路径下的所有注解 2.对需要实例化的类添加注解: Component注解是bean类实例化提供的 注解方式。它还衍生出三个注解,Control...

weixin_43243916的博客 532

Agisoft Metashape相机标定笔记

使用Metashape进行自动相机标定是可能的。(可选:使用打印的棋盘格图案,但需保证它是平坦的且单元格是正方形)。相机标定步骤支持全相机标定矩阵的估计,包含非线性的畸变参数。相机模型的细节请参照附录D——相机模型板块。:在通用的工作流程中,相机标定步骤可以跳过。因为Metashape会在图像定向过程中进行相机自标定。但是,如果定向结果不稳定,例如,由于影像之间缺乏连接点,额外进行单独的相机标定步骤也许是有用的。

天桥飞熊的博客 3972

【Spring【IOC】】——17、@Resource注解和@Inject注解?

Resource注解和@Autowired注解的功能是一样的,都能实现自动装配,只不过@Resource注解默认是按照组件名称(即属性的名称)进行装配的。虽然@Resource注解具备自动装配这一功能,但是它是不支持@Primary注解优先注入的功能的,而且也不能像@Autowired注解一样能添加required=false属性。

zhouhengzhe的博客 1533

【MagicDrive环境配置】新手配俩星期版

1.创建一个新的环境conda create -n newdrive python==3.82.激活该环境conda activate newdrive3.下载MagicDrive源码 git clone --recursive https://github.com/cure-lab/MagicDrive.git,如果出现时间超时八成是网的问题,直接自己下载解压就好3.我的cuda版本是11.7,但11.7导致后续安装有冲突,因此进入。

m0_46261292的博客 2203

【Qualcomm高通音频】如何封装音频控件?

音频代码涉及面很广,这篇文档介绍如何封装音频控件给HAL层使用。这里以AW87519芯片调试为例进行介绍封装音频控件和使用的方法。在最初接出到高通音频基础功能调试的时候,都是从tinyalsa指令/mixer_paths文件配置开始。因为单独一个音频设备的调试,都对应一条音频链路的打通。比如以下链接上高通平台基础音频输入输出设备调试: 【Qualcomm音频】Speaker 调试记录http...

crow_ch的博客 1954

spring之IoC注解(三)负责注入的注解

IoC是控制反转,指的是①、把创建对象的权利交出去,让别人创建,②、创建之后两个对象之间关系的维护也不管了,交给Spring去管理。spring去依赖注入。这四个注解是用来声明Bean的,声明后这些Bean将被实例化。如何给Bean的属性赋值?

qq_42338744的博客 1020

使用 Restart Extension 继续解决 Ansys 机械分析

您正在执行复杂或大型的多步有限元分析,突然,您意识到经过数小时的求解后,您需要添加或修改边界条件。在本篇博文中,您将了解如何利用 Ansys Mechanical 中的 RestartAnalysis 扩展来扩展多步分析,方法是合并额外的时间步骤和边界条件,而不会丢失已计算的结果。幸运的是,在 Mechanical 中,有一种直接的方法可以实现这一点,而不会损害您之前的结果,而这在添加新边界条件和使用重新启动点时经常发生。得到的结果符合预期,您可以看到施加的力产生的这两个部分之间的相对位移。

jkh920184196的博客 1232

有关spring的依赖注入和@resource注解的使用

控制反转(Inversion of Control)和依赖注入(Dependency Injection): IoC,直观地讲,就是容器控制程序之间的关系,而非传统实现中,由程序代码直接操控。这也就是所谓“控制反转”的概念所在。控制权由应用代码中转到了外部容器,控制权的转移是所谓反转。IoC还有另外一个名字——“依赖注入(Dependency Injection)”。从名字上理解,所谓依赖注入,

DING135DING的专栏 7733

816华为OD机试真题 新系统 - 电池充电时间计算 (Java/Py/C/C++/Js/Go)

816华为OD机试真题 新系统 - 电池充电时间计算 (Java/Py/C/C++/Js/Go)

算法大师! 469

SAP 权限配置(复合角色)

复合角色创建步骤:业务场景:通常单一角色权限颗粒度划分比较细,当需要分配单一角色权限A、B(多个单一角色)给某账号用户Y时,可以先建立一个复合角色C,将A、B绑定到复合角色C中,再将角色C分配给账号Y即完成权限配置。 业务模拟: 1、PFCG创建复合角色: 2、在角色页面添加子角色 在角色分页内添加子角色,点击“菜单”分页中的“读菜单”即可导入子角色中的菜单: 3、将用户分配给...

willieyuan的博客 7087

SpringIOC的bean自动注解(Resource,Autowired)

SpringIOC的bean自动注解(Resource,Autowired) org.xml.sax.SAXParseException; lineNumber: 11; columnNumber: 36; schema_reference.解决办法

weixin_47514459的博客 803

【生信分析】clusterProfiler: universal enrichment tool for functional and comparative study(1)

clusterProfiler: universal enrichment tool for functional and comparative studyClusterProfiler: 用于功能和比较研究的通用富集工具总览1. 引言1.1 术语1.1.1 基因集和通路1.1.2 基因同源(GO)1.1.3 京都基因与基因组百科全书(KEGG)1.1.4 其他基因集2. 功能富集分析方法2.1 过度表征分析(Over Representation Analysis)2.2 基因集富集分析(Gene Se

小哲的博客 1365

SpringIOC自动注入:@Resource注解注入

目前我本人正在学习SpringFramework的知识,这也是这个专栏的主题。我前面的几篇博文中,简单的认识了一下SpringFramework,记录了SpringFramework的环境搭建,记录了SpringIOC如何加载配置文件,记录了SpringIOC三种Bean对象的实例化方法。还记录了SpringIOC手动装配(注入)的方法之一:set方法注入。还有另外三个不太常用的SpringIOC手动注入的方法。其实目前大部分都使用的是自动注入的方法,手动注入使用的不多。就算是使用手动注入的方法,使用的主流

weixin_46281472的博客 3916

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

SSM SpringIoc(下)

但是实际开发时,基本上所有需要装配组件的地方都是必须装配的,用不上这个属性。在标题九中已经讲过xml方式配置调用方法,是在xml文件中指定bean组件并且填写init-method和destroy-method的属性。@Autowired注解默认根据类型装配,如果想根据名称装配,需要配合@Qualifier注解一起用。十四、DI装配的注解:@Autowired+Qualifier、@Resource与@Value。Spring 为了知道程序员在哪些地方标记了什么注解,就需要通过扫描的方式,来进行。

2401_88237139的博客 651

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

深入了解SpringIOC

简单来说,Bean 代指的就是那些被 IoC 容器所管理的对象。我们需要告诉 IoC 容器帮助我们管理哪些对象,这个是通过配置元数据来定义的。配置元数据可以是 XML 文件、注解或者 Java 配置类。下图简单地展示了 IoC 容器如何使用配置元数据来管理对象。和这两个包是 IoC 实现的基础,如果想要研究 IoC 相关的源码的话,可以去看看。

2303_78378466的博客 979

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

springioc单接口多实现类

springioc单接口多实现类 springioc单接口多实现类 导入依赖 spring-ioc配置文件 代码实现 BookController @Controller public class BookController { // @Autowired //根据类型注入 // //使用@autowired注入是根据类型,但是这里的多个实现类都是接口类型的, // // 所以需要根据name指定具体的注入哪个实现类 // @Qualifier("servic

abksio的博客 396

SpringIOC-注解

必须会背的注解@Component@Service@Resource@Autowired@Bean熟练使用注解完成三层架构的调用能详细描述@Resouce和@Autowired的区别配置类的配置和启动。

qing_fengcss的博客 1181

@Resource和@Bean

@Resource和@Bean的使用场景区分

m0_52710583的博客 900

手写SpringIOC 实现原理-注解版本-手写@Service和@Resource

手写SpringIOC注解版本 实体类: public class User { private Integer id; private String userName; public Integer getId() { return i...

qq_35524586的博客 679

@Autowired与@Resource注解的区别

而查找的分为两种实现,按名称byName和按类型byType查找,@Autowired是先根据类型查找,如果存在多个Bean,再根据名称查找,如果想按名称装配,可以结合@Qualifier注解一起使用。@Resource是先根据名称查找,如果根据名称查不到,再根据类型进行查找。@Autowired是Spring定义的注解,@Resource是Java定义的注解,Java250规范。@Resource更加通用,因为它是个规范,除了Spring,其他框架也可使用。支持优先注入,可以配置允许Bean不存在。

liziang888的博客 289

SpringIOC学习

如果对于一个类,突然需要代理了,那么以前是通过new出来的就会出问题.我们一个类的参生不应该通过new出来,应该面向抽象编程. IOC 和DI有什么区别和关系: IOC控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度.启动最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫"依赖查找"(Dependency Lookup) IOC是一种编程中需要达到的目标,DI是实现IOC的一种技

qq_41972358的博客 191

自定义注解@Bean和@Resource 实现SpringIOC

  在实际项目开发中,基本已经离不开spring框架了,而spring框架的成功之处在于起IOC以及AOP强大的解耦功能。今天给大家带来自己所简单实现的一个IOC注入。   编写@Bean以及@Resource注解 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Be...

weixin_30733003的博客 365

SpringIOC

Spring优点:1、方便解耦,简化开发,IOC控制反转Spring 就是一个大工厂,可以将所有对象创建和依赖关系维护交给Spring2、AOP 编程的支持Spring 提供面向切编程,可以方便的实现对序进行权限拦截、运监控等功能3、声明式事务的支持(张三给李四转账,要么同时成功,要么同时失败)只需要通过配置就可以完成对事务的管理,而无手动编程4、方便集成各种优秀框架。

2301_79704601的博客 1024

对比@Resource和@Autowired

在Java的Spring框架中,@Resource和@Autowired都是用于实现依赖注入(Dependency Injection, DI)的重要注解。依赖注入是一种实现控制反转(Inversion of Control, IoC)的设计模式,它允许将对象之间的依赖关系交由外部容器(如Spring IoC容器)来管理和注入,从而降低了代码之间的耦合度,提高了系统的可维护性和可扩展性。@Resource和@Autowired都能够帮助开发者自动装配bean,无需手动创建和配置对象之间的关系

谷哥的小弟 1290

@Resource/@PreDestroy/@PostConstruct注解不生效问题

在maven中使用Spring IOC注解时 @Resource/@PreDestroy/@PostConstruct注解不生效; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; javax.annotation包未生效; 此时:@Resource(name="XXX") 会报空指针异常...

Mr.Shu的博客 4327
上一篇: 代码实现SpringBoot内置tomcat与SpringMVC功能
下一篇: 代码实现SpringMVC基本功能
金心靖晨
博客等级 码龄9年 460粉丝 211原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值