手撕spring框架(5)

ops/2024/9/25 21:19:05/

spring5_0">手撕spring框架(5)

相关系列
手撕spring框架(1)
手撕spring框架(2)
手撕spring框架(3)
手撕spring框架(4)
这是本专题最后一节了,主要是讲述自定义一个注解,实现自定义值的引用,继承BeanPostProcessor接口,在对象创建的时候,注入到变量中。

注解DzendValue接口源码

package com.dzend.service;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;@Retention(java.lang.annotation.RetentionPolicy.RUNTIME
)
@Target(ElementType.FIELD)
public @interface DzendValue {String value() default "";
}

核心是定义一个默认值

定义DzendValueBeanPostProcessor类

package com.dzend.service;import com.spring.BeanPostProcessor;
import com.spring.Component;import java.lang.reflect.Field;@Component
public class DzendValueBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) {for (Field field : bean.getClass().getDeclaredFields()) {if (field.isAnnotationPresent(DzendValue.class)) {field.setAccessible(true);try{field.set(bean,field.getAnnotation(DzendValue.class).value());} catch (IllegalAccessException e) {e.printStackTrace();}}}return bean;}
}

继承BeanPostProcessor接口,并实现在初始后给属性赋值。

使用

添加新的代码
在上图标出来的代码是用来实现继承了BeanPostProcessor对象,在createBean的时候,创建完对象,来执行aop这块的业务逻辑,在初始化前和初始化后。
源码:

package com.spring;import java.beans.Introspector;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;public class DzendApplicationContext {private Class<?> configClass;private Map<String,BeanDefinition> beanDefinitionMap= new HashMap<>();private Map<String, Object> singletonObjects=new HashMap<>();private List<BeanPostProcessor> beanPostProcessorList = new ArrayList<>();public DzendApplicationContext(Class configClass)   {this.configClass=configClass;scan(configClass);}private void scan(Class configClass) {if(configClass.isAnnotationPresent(ComponentScan.class)){ComponentScan componentScan = (ComponentScan) configClass.getAnnotation(ComponentScan.class);String path = componentScan.value();path = path.replace(".","/");ClassLoader classLoader = DzendApplicationContext.class.getClassLoader();URL resource = classLoader.getResource(path);try {path = URLDecoder.decode(path, "UTF-8");} catch (UnsupportedEncodingException e) {throw new RuntimeException(e);}File file = null;try {file = new File(  URLDecoder.decode(resource.getFile(), "UTF-8"));} catch (UnsupportedEncodingException e) {throw new RuntimeException(e);}if(file.isDirectory()){for (File f : file.listFiles()) {String absolutePath = f.getAbsolutePath();absolutePath = absolutePath.substring(absolutePath.indexOf("com"),absolutePath.indexOf(".class"));absolutePath=absolutePath.replace("\\",".");try {Class<?>  clazz = classLoader.loadClass(absolutePath);if (clazz.isAnnotationPresent(Component.class)) {if (BeanPostProcessor.class.isAssignableFrom(clazz)) {BeanPostProcessor instance = (BeanPostProcessor) clazz.getConstructor().newInstance();beanPostProcessorList.add(instance);}Component componentAnnotaion = clazz.getAnnotation(Component.class);String beanName= componentAnnotaion.value();if("".equals(beanName)){beanName = Introspector.decapitalize(clazz.getSimpleName());}BeanDefinition beanDefinition = new BeanDefinition();beanDefinition.setType(clazz);if (clazz.isAnnotationPresent(Scope.class)) {Scope scopeAnnotation = clazz.getAnnotation(Scope.class);String value = scopeAnnotation.value();beanDefinition.setScope(value);}else{beanDefinition.setScope("singleton");}beanDefinitionMap.put(beanName,beanDefinition);}} catch (ClassNotFoundException e) {e.printStackTrace();} catch (InvocationTargetException e) {throw new RuntimeException(e);} catch (InstantiationException e) {throw new RuntimeException(e);} catch (IllegalAccessException e) {throw new RuntimeException(e);} catch (NoSuchMethodException e) {throw new RuntimeException(e);}}}}}public Object getBean(String beanName){if(!beanDefinitionMap.containsKey(beanName)){throw new NullPointerException();}BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);if(beanDefinition.getScope().equals("singleton")){Object singletonObject = singletonObjects.get(beanName);if(singletonObject == null){singletonObject = createBean(beanName,beanDefinition);singletonObjects.put(beanName,singletonObject);}return singletonObject;}else{//原型Object prototypeBean = createBean(beanName, beanDefinition);return prototypeBean;}}private Object createBean(String beanName, BeanDefinition beanDefinition) {Class clazz = beanDefinition.getType();Object instance = null;try {instance = clazz.getConstructor().newInstance();for (Field field : clazz.getDeclaredFields()) {if(field.isAnnotationPresent(Autowired.class)){field.setAccessible(true);field.set(instance,getBean(field.getName()));}}if(instance instanceof BeanNameAware){((BeanNameAware) instance).setBeanName(beanName);}for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {instance = beanPostProcessor.postProcessBeforeInitialization(instance,beanName);}if(instance instanceof InitializingBean){((InitializingBean) instance).afterPropertiesSet();}for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {instance = beanPostProcessor.postProcessAfterInitialization(instance,beanName);}} catch (InstantiationException e) {throw new RuntimeException(e);} catch (IllegalAccessException e) {throw new RuntimeException(e);} catch (InvocationTargetException e) {throw new RuntimeException(e);} catch (NoSuchMethodException e) {throw new RuntimeException(e);}return instance;}
}

以上是最终的代码,本专题基本上讲完了一个简单的spirng框架的实现,是从0开始构建的,希望帮帮助大家对spring有一定的认识,当然,这是只是个简化版本。


http://www.ppmy.cn/ops/32749.html

相关文章

xss注入漏洞解析(下)

DOM型XSS 概念 DOM全称Document Object Model&#xff0c;使用DOM可以使程序和脚本能够动态访问和更新文档的内容、结 构及样式。DOM型XSS其实是一种特殊类型的反射型XSS&#xff0c;它是基于DOM文档对象模型的一种漏洞。 HTML的标签都是节点&#xff0c;而这些节点组成了DOM的…

Pytorch实现扩散模型【DDPM代码解读篇1】

本篇内容属于对DDPM 原理-代码 项目的解读。 具体内容参考一篇推文&#xff0c;里面对DDPM讲解相对细致&#xff1a; 扩散模型的原理及实现&#xff08;Pytorch&#xff09; 下面主要是对其中源码的细致注解&#xff0c;帮助有需要的朋友更好理解代码。 目录 ConvNext块 正…

第III章-ⅠVue3进阶语法

vue3进阶语法 setup 函数Vue方法计算属性及监听器methods方法 computed计算属性ref函数 watch 监听器Vue的表单绑定v-model实现表单绑定v-model修饰符 setup 函数 Vue 3 引入了组合式 API&#xff0c;其中核心是 setup 函数。这个函数是组件中所有 Composition API 特性的入口…

设计模式一

单例模式&#xff08;Singleton Pattern&#xff09;是一种常用的软件设计模式&#xff0c;旨在确保一个类只有一个实例&#xff0c;并提供一个全局访问点。单例模式常用于控制资源密集型对象的创建&#xff0c;如数据库连接池、线程池等&#xff0c;以避免资源浪费。 单例模式…

SpringBoot之文件操作记录存储服务

概述 应公司安全管理部门政策要求,需要实现文件上传/下载操作的日志记录,经过分析需要在目前平台上基于springboot搭建一套服务供其他应用具体业务调用,其中该服务涉及到的技术支撑&#xff1a;AOP实现异常处理、queuespring-scheduler异步执行定时任务、Fegin组件进行服务间通…

基于springboot的汽车资讯网站源码数据库

基于springboot的汽车资讯网站源码数据库 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了汽车资讯网站的开发全过程。通过分析汽车资讯网站管理的不足&#xff0c;创建了一个计算机管理汽车资讯网站的方案。文章介…

Claude聊天机器人推出全新iOS客户端及团队专属计划

Anthropic 正在使其 Claude AI 更易于在移动设备上访问。该公司发布了适用于 iOS 的 Claude 移动应用程序,任何用户都可以免费下载。与聊天机器人的移动网络版本类似,该应用程序跨设备同步用户与 Claude 的对话,允许他们从计算机跳转到应用程序(反之亦然),而不会丢失聊天…

【Docker】搭建一个媒体服务器插件后端API服务 - MetaTube

【Docker】搭建一个媒体服务器插件后端API服务 - MetaTube 前言 本教程基于群晖的NAS设备DS423的docker功能进行搭建&#xff0c;DSM版为 7.2.1-69057 Update 5。 简介 MetaTube 是一个媒体服务器插件&#xff0c;主要用于 Emby 和 Jellyfin 媒体服务器。它的主要功能是从互…