在Spring中,我们可以通过 @Autowired注解的方式为一个方法中注入参数,那么这种方法背后到底发生了什么呢,这篇文章将讲述如何用Java的注解和反射实现一个“低配版”的依赖注入。

下面是我们要做的一些事情:

  1. 通过 @interface的方式定义一个注解
  2. 为某个希望杯被注入的方法添加这个注解
  3. 编写测试代码,通过反射获取添加了注解的方法对应的Method对象,将该方法对象设置为可访问的,通过反射创建对象并调用这个方法,同时注入依赖数据

如上所述,我们分为三个步骤, 去加工出这个低配版的依赖注入,下面就来讲讲每一步的详细步骤

我们要编写的代码的结构分为三部分:

  • Autowired: 声明的注解
  • Demo类:含有被依赖注入的方法setStr
  • Test类:通过反射获取被Autowired注解的方法,并进行依赖注入

一:定义注解

Autowired

@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {
}

首先我们通过 @interface的方式定义的一个注解, 由此也可以看出注解的地位和类,接口类似,是一种同一级的关系

@Retention是元注解,故名思义,它是用来注解(动词)注解(名词)的注解!(名词),RetentionPolicy.RUNTIME 表示会将这个注解保留到运行时,这样的话我们就能通过反射去处理注解了。

二. 为被注入的方法添加注解

下面我们为setStr方法添加一个注解

public class Demo {
private String str; @Autowired
public void setStr (String str) {
this.str = str;
} public String getStr () {
return str;
}
}

三. 通过反射处理注解

通过反射的方式获取并处理被注解的方法,将该方法对象设置为可访问的,通过反射创建对象并调用这个方法,同时注入依赖数据

由于涉及到大量关于反射的API,所以对于反射机制话可以看看我以前写的这篇文章: https://www.cnblogs.com/penghuwan/p/7580145.html

在这一步骤我们要做的事情:

  1. 调用Class.forName方法,传入某个类的路径字符串为参数,获取该类的Class对象
  2. 通过调用该类Class对象的getDeclaredMethods方法,获得声明方法对应的Methods对象组成的数组
  3. 遍历2中的Methods数组,通过调用Method对象的isAnnotationPresent方法判断该方法有没有加上Autowired注解,并对其中加上Autowired注解的方法做以下处理
  4. 通过调用Method对象的setAccessible(true);方法将对象设置为可访问的,不这么搞下一步调用方法会出错
  5. 通过Class对象的newInstance方法创建对象实例,假设其为object,则再通过method.invoke(object, “传入的数据")调用对象的方法,注入依赖数据
  6. 将5中的对象实例object返回, 我们就获得了被注入了依赖数据的对象实例了

代码如下:

Test.java

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; public class Test {
/**
* 这个方法会将一段文本注入到某个类中添加了@Autowired注解的方法中,并将实例对象返回
*/
public static Object injectStrToInstance (String ClassName,String str) throws ClassNotFoundException {
// 获取Demo的Class对象
Class demoClass = Class.forName(ClassName);
// 从Class对象中获取Demo中声明方法对应的Method对象
Method [] methods = demoClass.getDeclaredMethods();
for (Method method : methods) {
// 判断方法是否被加上了@Autowired这个注解
if(method.isAnnotationPresent(Autowired.class)) {
// 将方法设置为可调用的
method.setAccessible(true);
try {
Object object = demoClass.newInstance();
// 调用method方法,向其中注入str字符串
method.invoke(object,str);
return object;
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}
return null;
} public static void main (String args []) throws ClassNotFoundException {
// 进行依赖注入,并取得注入后的Demo的对象实例
Demo demo1 = (Demo)injectStrToInstance("Demo", "我是被注入的文本");
// 输出一下看看我们的文本是不是被成功注入进去了
System.out.println(demo1.getStr());
}
}

输出结果:

我是被注入的文本

到此为止, 我们就完成了这个低配版的依赖注入了

【Java】利用注解和反射实现一个"低配版"的依赖注入的更多相关文章

  1. 【Node/JavaScript】论一个低配版Web实时通信库是如何实现的( WebSocket篇)

    引论 simple-socket是我写的一个"低配版"的Web实时通信工具(相对于Socket.io),在参考了相关源码和资料的基础上,实现了前后端实时互通的基本功能 选用了Web ...

  2. 【JavaScript】论一个低配版Web实时通信库是如何实现的之二( EventSource篇)

    前情提要 「 话说上回说到!那WebSocket大侠,巧借http之内力,破了敌阵的双工鸳鸯锁,终于突出重围. 然而玄难未了,此时web森林中飞出一只银头红缨枪,划破夜色. "莫非!?&qu ...

  3. java利用注解及反射做通用的入参校验

    一.原理: 1.做一个field注解,注解有两个参数:是否必填.toString之后的最大长度 2.对某个request类(或基类),使用注解标记某个字段的校验详情 3.通用的static方法,利用反 ...

  4. java使用注解和反射打造一个简单的jdbc工具类

    a simple jdbc tools 如有转载和引用,请注明出处,谢谢 1. 定义我们需要的注解 要想实现对数据库的操作,我们必须知道数据表名以及表中的字段名称以及类型,正如hibernate 使用 ...

  5. 搭建一个低配版的Mock Server

    mock翻译过来是模仿的意思,Server是服务器.粗暴点直译就是模仿服务器. 写在前面 通过阅读本文,你将对Mock的使用有一定的了解,对前后端分离的概念有了更深一步的认识,对Koa的使用有一定的了 ...

  6. 基于canvas和web audio实现低配版MikuTap

    导言 最近发掘了一个特别happy的网页小游戏--MikuTap.打开之后沉迷了一下午,导致开发工作没做完差点就要删库跑路了,还好boss瞥了我一眼就没下文了.于是第二天我就继续沉迷,随着一阵抽搐,这 ...

  7. Java基于注解和反射导入导出Excel

    代码地址如下:http://www.demodashi.com/demo/11995.html 1. 构建项目 使用Spring Boot快速构建一个Web工程,并导入与操作Excel相关的POI包以 ...

  8. 使用Java元注解和反射实现简单MVC框架

    Springmvc的核心是DispatcherServlet来进行各种请求的拦截,进而进行后续的各种转发处理.流程图如下: 说明:客户端发出一个http请求给web服务器,web服务器对http请求进 ...

  9. Java之注解与反射

    Java之注解与反射 注解(Annotation)简介 注解(Annotation)是从JDK5.0引入的新技术 Annotation作用:注解(Annotation)可以被其他程序如编译器等读取 A ...

随机推荐

  1. vue的事件处理梳理

    一.事件函数 1.v-on绑定click,执行一个函数 <input type="button" v-on:click="test" value=&quo ...

  2. sort排序在苹果与安卓端不一致问题

    一.问题 在使用sort排序时,若遇到相同数据或非数值数据时,会出现苹果手机与安卓手机排序不一致问题 var arr = [{ "id": "52", &quo ...

  3. 分割list,将集合按规定个数分为n个部分。

    /** * 按指定大小,分隔集合,将集合按规定个数分为n个部分 * * @param list * @param len * @return */ public static <T> Li ...

  4. Vue中观察者模式的实现

    Vue中实现观察者模式的方法可以有三种: 1.v-on方法 exp: <div id='test'> <button v-on:event='functionName'>but ...

  5. wsl

    1.win10设置为开发人员模式,并安装subsystem for linux(命令行输入bash就可以安装) 2.登录并su到root,然后修改/etc/sudoers,在最后一行加(一定要在最后一 ...

  6. dskinlite(uieasy mfc界面库)使用记录3:绘制动态元素(按钮控件通过隐藏方式修改图片显示)

    效果图: 分别是:正常,正常鼠标悬停,按下,按下鼠标悬停 XML代码: 75,76行定义了一个image,注意id和index属性 初始化代码: click代码: 147,148,153,154:通过 ...

  7. class 关键字

    class Ninja 表示创建一个名为Ninja的函数.constructor(...)指明Ninja函数的签名和函数体内容. class Ninja{ constructor(name){ thi ...

  8. mongodb参数

    启动命令 : mongod -port --dbpath data/ --logpath log/mongodb.log --fork ps -ef | grep momgod (查看是否启动成功) ...

  9. Linux内核基本装载卸载

    Linux由两部分组成:内核核心+内核模块核心的命名通常是vmlinuz-VERSION-release,模块的放置于/lib/modules/VERSION-release/ 一旦系统运行起来,内核 ...

  10. AHK控制鼠标与键盘

    F4::clicksleep 100MouseGetPos, xpos, ypos x:=xpos+30 click 1877,51sleep 100click 115,51sleep 100clic ...