浅析spring中注解的运行

2023-05-16

为了了解注解的运行机制,需要自定义一个注解,如下方式来模拟注解方式实现注入对象:
1.新建一个自定义注解MyResource.java

@Retention(RetentionPolicy.RUNTIME) // 定义注解有效期为运行期
@Target({ElementType.FIELD,ElementType.METHOD}) // 定义可以注解的位置
public @interface MyResource {
    String name() default "";
}

2.自定义spring中的注解运行

package com.heying.test;

import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;

import com.heying.service.MyResource;
import com.heying.service.PropertyDdefinition;
import com.heying.service.XmlBeanDefinition;

public class MyClassPathXmlApplicationContext {
    private List<XmlBeanDefinition> beanDefinitions = new ArrayList<XmlBeanDefinition>();
    private Map<Object, Object> sigletons = new HashMap<Object, Object>();

    public MyClassPathXmlApplicationContext(String fileName) {
        this.readXmlFile(fileName);
        this.instanceBeans();
        this.annotationInject();
        this.injectObject();
    }

    /**
     * 注解
     */
    private void annotationInject() {
        for (Object beanName : sigletons.keySet()) {
            Object bean = sigletons.get(beanName);
            if(bean != null){
                try {
                    PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
                    for (PropertyDescriptor propertyDescriptor : ps) {
                        Method setter = propertyDescriptor.getWriteMethod();    
                        if(setter != null && setter.isAnnotationPresent(MyResource.class)){
                            MyResource myTest = setter.getAnnotation(MyResource.class); //获取注解

                            if(myTest.name() != null && !"".equals(myTest.name())){
                                Object value = sigletons.get(myTest.name());
                                setter.setAccessible(true);
                                setter.invoke(bean,value); // 引入对象到属性
                            }else{ 
                                Object value = sigletons.get(propertyDescriptor.getName());
                                // 没有标注name 或者没有找到的时候就会按照类型去寻找
                                if(value == null){
                                    for (Object key : sigletons.keySet()) {
                                        if(propertyDescriptor.getPropertyType().isAssignableFrom(sigletons.get(key).getClass())){
                                            value = sigletons.get(key);
                                            setter.setAccessible(true);
                                            setter.invoke(bean,value); // 引入对象到属性
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                    }

                    Field[] fields = bean.getClass().getDeclaredFields();
                    for (Field field : fields) {
                        if(field.isAnnotationPresent(MyResource.class)){
                            MyResource myTest = field.getAnnotation(MyResource.class); //获取注解
                            Object value = null;
                            if(myTest.name() != null && !"".equals(myTest.name())){
                                 value = sigletons.get(myTest.name());
                            }else{ 
                                 value = sigletons.get(field.getName());
                                // 没有标注name 或者没有找到的时候就会按照类型去寻找
                                if(value == null){
                                    for (Object key : sigletons.keySet()) {
                                        if(field.getType().isAssignableFrom(sigletons.get(key).getClass())){
                                            value = sigletons.get(key);
                                            break;
                                        }
                                    }
                                }
                            }
                            field.setAccessible(true);
                            field.set(bean, value);
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 依赖注入
     */
    private void injectObject() {
        for ( XmlBeanDefinition beanDefinition : beanDefinitions) {
            Object bean = sigletons.get(beanDefinition.getId());
            if(bean != null){
                try {
                    PropertyDescriptor[] propers = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();

                    for (PropertyDdefinition propertyDdefinition : beanDefinition.getDdefinitions()) {
                        for (PropertyDescriptor propertyDescriptor : propers) {
                            if(propertyDdefinition.getName().equals(propertyDescriptor.getName())){  // 判断是否相等
                                Method setter = propertyDescriptor.getWriteMethod(); // 获取set方法
                                if(setter != null){
                                    Object value = sigletons.get(propertyDdefinition.getRef());
                                    setter.setAccessible(true);
                                    setter.invoke(bean,value); // 引入对象到属性
                                }
                                break;
                            }
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * bean 实例化
     */
    private void instanceBeans(){
        for ( XmlBeanDefinition beanDefinition : beanDefinitions) {
            try {
                if(beanDefinition.getName() != null && !"".equals(beanDefinition.getName())){
                    sigletons.put(beanDefinition.getId(), Class.forName(beanDefinition.getName()).newInstance());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 读取XML信息
     * @param fileName
     */
    @SuppressWarnings("unchecked")
    private void readXmlFile(String fileName) {
        SAXReader saxReader = new SAXReader();
        Document document = null;

        try {
            URL xmlPath = this.getClass().getClassLoader().getResource(fileName); // 获取相对路径
            document = saxReader.read(xmlPath); // 读取xml文件

            Map<String, String> nsMap = new HashMap<String, String>();
            nsMap.put("ns", "http://www.springframework.org/schema/beans"); // 加入命名空间
            XPath xPath = document.createXPath("//ns:beans/ns:bean"); // 创建查询路径
            xPath.setNamespaceURIs(nsMap); // 设置命名空间

            List<Element> beans = xPath.selectNodes(document); // 获取所有节点
            for (Element element : beans) {
                String id = element.attributeValue("id");
                String clazz = element.attributeValue("class");
                XmlBeanDefinition xmlBeanDefinition = new XmlBeanDefinition(id, clazz);

                XPath propertysub = document.createXPath("ns:property");
                propertysub.setNamespaceURIs(nsMap); // 设置空间

                List<Element> propertys = propertysub.selectNodes(element);
                for (Element property : propertys) {
                    String propertyName = property.attributeValue("name");
                    String propertyRef = property.attributeValue("ref");
                    System.out.println("[propertyName="+propertyName+",propertyRef="+propertyRef+"]");
                    PropertyDdefinition ddefinition = new PropertyDdefinition(propertyName, propertyRef);
                    xmlBeanDefinition.getDdefinitions().add(ddefinition);
                }
                beanDefinitions.add(xmlBeanDefinition);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取bean实例
     * @param beanName
     * @return
     */
    public Object getBean(String beanName){
        return this.sigletons.get(beanName);
    }
}

输出的结果和使用j2ee的注解有相同的效果

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

浅析spring中注解的运行 的相关文章

  • Windows核心编程之邮槽实现进程间通信

    邮槽是Windows系统提供的一种单向通信的机制 即进程中的一方只能写入或读取数据 xff0c 而另一方则只能读取或写入数据 通过邮槽 xff0c 用户可以实现一对多或跨网络的进程之间的通信 但是 xff0c 邮槽能传输的数据非常小 xff
  • 图像连通域分析

    转自 xff1a https blog csdn net tiandijun article details 51279643 xff0c 转载仅为方便学习 一 前言 二值图像的图像的亮度值只有两个状态 xff1a 黑 0 和白 255 二
  • C++ wchar_t *和char * 互转

    转自 xff1a https blog csdn net lightspear article details 54695123 说道wchar t和char两个类型大家都不会陌生 wchar t xff1a 在windows下是Unico
  • android识别模拟器

    识别安卓模拟器的两种方案 xff01 禁止通过模拟器进行刷量 xff0c 防止作弊行为 xff01 import android content Context import android content Intent import an
  • ubuntu在终端中打开文件管理器

    打开ubuntu的终端 xff0c 输入nautilus path 弹出资源管理器界面
  • chrome jsonView插件安装

    由于谷歌浏览器经常打不开应用商店 xff0c 还有就是安装第三方插件的办法 方法就如下 xff1a 由于最近做和json相关的东西 xff0c 所以 xff0c 以jsonView插件为例分享一下 1 打开https github com
  • Gradle学习笔记 使用Gradle Wrapper

    Gradle可以在没有安装Gradle的情况下使用 xff0c 这时候就需要Gradle Wrapper了 Gradle Wrapper其实就是一个脚本文件 xff0c 它会在没有安装Gradle的情况下为我们下载Gradle xff0c
  • 《30天自制操作系统》:值得推荐的一本好书

    自己编写一个操作系统 xff0c 是许多程序员的梦想 也许有人曾经挑战过 xff0c 但因为太难而放弃了 其实你错了 xff0c 你的失败并不是因为编写操作系统太难 xff0c 而是因为没有人告诉你那其实是一件很简单的事 那么 xff0c
  • 验证谷角猜想

    import java util public class Test3 3 验证谷角猜想 xff1a 日本数学家谷角静夫在研究自然数时发现了一个奇怪的现象 对于任意一个自然数n xff0c 若n为偶数 xff0c 则将其除以2 xff1b
  • 生产者消费者问题(Linux多线程下两种实现)

    生产者消费者问题是同步问题中的一种常见情况 xff0c 借用一下维基百科的话 生产者消费者问题 xff08 英语 xff1a Producer consumer problem xff09 xff0c 也称 有限缓冲问题 xff08 英语
  • Mac Tomcat安装 localhost 拒绝了我们的连接请求

    Mac Tomcat安装 localhost 拒绝了我们的连接请求 Mac下安装Tomcat服务器 xff0c 下载的Tomcat10 在bin目录下 xff0c 授权 chmod 777 sh 启动Tomcat服务 startup sh
  • 从SAP最佳业务实践看企业管理(83)-PP-145按库存生产

    xfeff xfeff 从SAP 最佳业务实践看企业管理 83 PP 145 按库存生产 1 MTS 按库存生产 在按库存生产策略的类型中 xff0c 客户基本上对最终产品规格的确定没有什么建议或要求 xff0c 他们的投入很少 生产商生产
  • Jenkins学习笔记:解决插件安装问题

    安装插件结束后 xff0c 当时界面提示很多插件没有成功 xff0c 问我是否需要重试 xff0c 我安排到后面再做解决 今天打开Jenkins后 xff0c 发现之前的密码不能登录了 xff0c 仔细想了想 xff0c 记起之前改过了 用
  • Tensorflow lite for 移动端安卓开发(二)——完整详细过程训练自己的模型

    官方给的Tensorflow lite demo是ImageNet 中训练的1000类物体识别 xff0c 基于移动端的项目需要 xff0c 现在要用模型训练自己的数据 xff0c 提供两种训练方法 xff0c 这也是自己在摸索Tensor
  • 亚马逊,一个沉睡广告巨人的苏醒(虎嗅网)

    虽然拥有令无数广告主羡慕的高质量用户数据和巨大的网站流量 xff0c 但是在很长的一段时间内亚马逊还是将主要的精力集中在商品销售上 xff0c 广告只是作为自身业务的补充可有可无的存在 不过最近两年 xff0c 亚马逊对广告这种不屑的态度正
  • 大数据案例分析:电信业Hadoop应用分析 原文出自【比特网】,转载请保留原文链接:http://do.chinabyte.com/228/12410228.shtml

    电信业Hadoop应用分析 昨日 xff0c 联通研究院处长王志军在第七届 开源中国 开源世界 高峰论坛上分享了Hadoop在电信行业大数据应用的经验 随着国内3G网络的发展 xff0c 或者移动通信网络的发展 xff0c 中国联通 600
  • 大腕出手看门道,谈BAT的投资战略差异 三家战略投资的思考原点并不相同虎嗅网)

    中国互联网的收购之战 xff0c 比娱乐圈的明星离婚更一波三折和猜不透结局 当所有人以为搜狗被360牵回山寨只是早晚的事的时候 xff0c 搜狗和腾讯宣布好上了 眼瞅着今年第三季度即将结束 xff0c 中国互联网巨头们在2013年的 军备竞
  • JDK6的安装

    http www java net download jdk6 6u10 promoted b32 binaries jdk 6u10 rc2 bin b32 windows i586 p 12 sep 2008 exe XP 下 JDK6
  • 如何利用大数据进行价值兑现才是正经事(虎嗅网)

    如果有一天你可以预测未来 xff0c 你要做的第一件事情是什么 xff1f 买彩票 xff1f 第二件 第三件事情呢 xff1f 先卖个关子 xff0c 我们后面再说这件事情 大数据是个产业 xff0c 广义上指的是在这个信息过载时代围绕着
  • 络达开发---串口日志&日志过滤

    平台 xff1a AB1565M SDK版本 xff1a V2 11 0 开发环境 xff1a windows10 采用官方ATK中的日志工具可以通过硬件物理串口来实时查看芯片中软件的运行日志 如下图所示 xff0c 其实该ATK工具为一若

随机推荐

  • 多图震撼!数字的未来,2013报告(虎嗅网)

    新媒体 完爆 旧媒体 从市值上来看 xff0c 以苹果 谷歌 亚马逊 Facebook 雅虎等为首的新媒体公司市值已超过1万亿美元 xff0c 而以迪斯尼 Comcast 时代华纳 Viacom CBS 新闻集团 21世纪福克斯等为首的旧媒
  • 网页采集器-八爪鱼采集器

    八爪鱼采集器下载地址 xff1a http www bazhuayu cc download 八爪鱼采集器的注册地址 xff1a http www bazhuayu cc signup id 61 0e492e9c 6d80 4c2a a2
  • 考研书单与技巧

    书尽量在网上搞活动时买正版的 xff0c 这样也不贵 每科研究透一到两本书 xff0c 不要贪多 xff01 1 英语 xff1a xff08 积累的过程 xff0c 可以现在开始 xff0c 正好把六级过了 xff09 xff08 看好所
  • Tomcat 9安装配置教程

    首先 xff0c 先去这个网址下载Tomcat 9 http tomcat apache org 然后根据自己的电脑系统版本去下载相对应的文件 xff01 我的系统版本是 Windows 10 64位 xff0c 所以我选择 34 64 b
  • Ef Core 使用Entity方式配置外键

    一 Ef Core 使用Entry方式配置外键 当一个表中有多个外键指向同一个表时候 xff0c 需要使用Entity方式执行具体外键约束名称 xff0c 使用方法如下 xff1a protected override void OnMod
  • Python安装后目录在哪儿_如何查看Python的安装目录

    一 Python的安装录 当前安装版本为 xff1a python 3 10 4 1 在安装python的时候可以看到安装目录 xff0c 可以修改安装目录 xff1a 2 windows系统下64位安装目录如下 xff1a 跟其他软件不太
  • linux下完全删除mysql

    linux下完全删除mysql 查询所有mysql的服务并停止所有mysql服务 查询自启服务列表 span class token function chkconfig span list 执行结果 mysqld 0 关闭 1 关闭 2
  • linux安装mysql-8.0.19-最全讲解

    linux离线方式安装mysql 8 0 19 下载mysql包 注意 在MySQL Server 8 0 12中 xff0c 压缩算法从Gzip更改为XZ xff1b 并且通用二进制文件的文件扩展名从 tar gz更改为 tar xz 安
  • Windows环境下给oracle打补丁详细教程

    环境检查 1 检查oracle数据库版本 xff0c 安装前检查 xff1a 确保Oracle数据库安装与您正在应用此修补程序的版本相同 C WINDOWS system32 span class token operator gt spa
  • CentOS7安装docker

    安装docker docker官网 xff1a http www docker com docker中文网站 xff1a https www docker com 仓库 Docker Hub官网 https hub docker com 官
  • springCloud---替换注册中心eureka为nacos后 @Value 获取不到值

    在替换为nacos后 xff0c 启动时出现如下错误 xff1a 64 Value 获取不到值 xff0c 无法解析 test 占位符 此时就会进行各种百度 xff0c google xff0c 查文档 xff01 而我遇到的问题出现在 x
  • Linux防火墙及端口策略设置(iptables&firewalld)

    防火墙设置 service firewalld stop service firewalld start service firewall restart service firewalld status 开机禁用 xff1a system
  • windows环境下安装MySQL8.0.19

    安装过程中可能提示缺少xx dll文件 xff0c 建议首先安装微软常用运行库集合 下载地址 1 下载MySQL8压缩包 xff0c 进行解压 xff0c 在根目录下创建data文件夹 xff0c 创建my ini配置文件 2 在配置文件中
  • 解决多个tomcat端口冲突

    我在一台PC机上安装了两个tomcat xff0c 需要同时启动 xff0c 每个tomcat上跑一个程序 xff0c 但是现在提示端口号冲突 xff0c 需要手动更改 需要修改三个地方 xff1a 1 首先 xff1a 在Tomcat的根
  • Android JsonArray移除里面的一个对象

    remove是在 API level 19 时加入的 xff0c 在低版本调用时会出现错误 这里用反射实现了兼容老版本的方法 public void Remove int positon throws Exception if positi
  • libgtk2.0-dev 安装broken packages问题解决方法

    在安装opencv的过程中 xff0c 需要安装到 libgtk2 0 dev xff0c 安装过程中可能会出现broken packages的问题 输出信息如下 xff1a apt get install libgtk2 0 dev Re
  • vue 代码格式化(VS code)

    1 安装了vetur xff08 Vue tooling for VS Code xff09 扩展插件 在扩展中搜索vetur xff0c 然后点击安装 2 直接 xff08 或者 选中你想格式化的代码 xff09 xff0c 右键 xff
  • ViewBinding与Kotlin委托

    接上篇幅 自定义属性委托的用处很多 xff0c 例如组合替代继承 xff0c 给个ViewBinding在Fragment中的使用的例子 xff1a 委托 自定义属性委托 lt p gt lt p gt lt ul gt lt li gt
  • Android之使用Kotlin构建Gradle

    Android StudioGradle3 4 25 1 1 首先kotlin dsl不是什么新鲜的东西了 xff0c Gradle5 0发布的时候就有了 Gradle Kotlin DSL目前的版本是1 0 2 现在是否可以抛弃groov
  • 浅析spring中注解的运行

    为了了解注解的运行机制 xff0c 需要自定义一个注解 xff0c 如下方式来模拟注解方式实现注入对象 xff1a 1 新建一个自定义注解MyResource java span class hljs annotation 64 Reten