使用Java注解模拟spring ioc容器过程解析

 更新时间:2020年07月07日 11:23:54   投稿:yaominghui  
这篇文章主要介绍了使用Java注解模拟spring ioc容器过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

使用注解,简单模拟spring ioc容器。通过注解给对象属性注入值。

项目结构

annotation 包,用于存放自定义注解

Component 注解表示该类为组件类,并需要声明名字

package priv.haidnor.annotation;

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

/**
 * 组件
 */
@Target(value = ElementType.TYPE)
@Retention(value = RetentionPolicy.RUNTIME)
public @interface Component {
	String name();
}

Value 注解用于给类的属性赋值

package priv.haidnor.annotation;

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

/**
 * 字段值
 */
@Target(value = ElementType.FIELD)
@Retention(value = RetentionPolicy.RUNTIME)
public @interface Value {
	String value();
}

ioc 包

package priv.haidnor.ioc;

import priv.haidnor.annotation.Component;
import priv.haidnor.annotation.Value;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

public class ApplicationContext {

	/**
	 * IOC 控制反转容器,在加载类的时候创建 HashMap , 并存入指定对象
	 */
	private static Map<String, Object> ioc;

	static {
		try {
			// 初始化 IOC 容器
			ioc = new HashMap<String, Object>();

			// 反射获得 Class 对象
			Class<?> clazz = Class.forName("priv.haidnor.pojo.Person");

			// 获取指定注解
			Component componentClass = clazz.getAnnotation(Component.class);

			// 获取指定注解的值
			String key = componentClass.name();

			// 通过反射创建对象
			Object object = clazz.newInstance();
			ioc.put(key, object);

			// 获取 Java Bean 所有的字段
			Field[] fields = clazz.getDeclaredFields();

			for (Field field : fields) {
				// 字段类型
				Class<?> type = field.getType();

				// 根据字段名生成 set 方法
				String filedName = field.getName();
				String methodName = produceSetMethodName(filedName);

				// 获得 Value 注解
				Value valueAnnotation = field.getAnnotation(Value.class);

				// 获得注解的值
				String theValue = valueAnnotation.value();

				// 构造 Method 对象
				Method method = clazz.getDeclaredMethod(methodName, field.getType());

				// 将注解参数转换类型
				Object value = typeConversion(field.getType(), theValue);

				// 执行 set 方法
				method.invoke(object, value);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 类型转换。将 String 字符串转换为指定数据类型类型的值
	 * @param typeClass 字段类型
	 * @param value 注解值
	 * @return 字符串转换为指定数据类型类型的值
	 */
	private static Object typeConversion(Class<?> typeClass, String value) {
		if (typeClass == int.class || typeClass == Integer.class) {
			if (value == null) {
				return 0;
			}
			return Integer.valueOf(value);
		} else if (typeClass == short.class) {
			if (value == null) {
				return 0;
			}
			return Short.valueOf(value);
		} else if (typeClass == byte.class) {
			if (value == null) {
				return 0;
			}
			return Short.valueOf(value);
		} else if (typeClass == double.class) {
			if (value == null) {
				return 0;
			}
			return Double.valueOf(value);
		} else if (typeClass == long.class) {
			if (value == null) {
				return 0;
			}
			return Long.valueOf(value);
		} else if (typeClass == String.class) {
			if (value == null) {
				return "";
			}
			return value;
		} else if (typeClass == Boolean.class) {
			if (value == null) {
				return false;
			}
			return Boolean.valueOf(value);
		} else if (typeClass == BigDecimal.class) {
			if (value == null) {
				return new BigDecimal(0);
			}
			return new BigDecimal(value + "");
		} else {
			return typeClass.cast(value);
		}
	}

	/**
	 * 拼接字符串,生成 set 方法名
	 * @param filedName 字段名
	 * @return set方法名,例如传入"name",则返回"setName"
	 */
	private static String produceSetMethodName(String filedName) {
		return "set" + filedName.substring(0, 1).toUpperCase() + filedName.substring(1);
	}

	/**
	 * 从容器中获得指定对象
	 * @param name 对象名称
	 * @return IOC 容器中的对象
	 */
	public static Object getBean(String name) {
		return ioc.get(name);
	}
}

pojo 包

package priv.haidnor.pojo;

import priv.haidnor.annotation.Component;
import priv.haidnor.annotation.Value;

@Component(name = "man")
public class Person {

	@Value("张三")
	private String name;

	@Value("男")
	private String gender;

	@Value("中国")
	private String country;

	@Value("23")
	private Integer age;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getGender() {
		return gender;
	}

	public void setGender(String gender) {
		this.gender = gender;
	}

	public String getCountry() {
		return country;
	}

	public void setCountry(String country) {
		this.country = country;
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "Person{" +
				"name='" + name + '\'' +
				", gender='" + gender + '\'' +
				", country='" + country + '\'' +
				", age=" + age +
				'}';
	}
}

测试类

import priv.haidnor.ioc.ApplicationContext;
import priv.haidnor.pojo.Person;

/**
 * 测试类
 */
public class Demo {
	public static void main(String[] args) {
		Person person = (Person) ApplicationContext.getBean("man");
		System.out.println(person);
	}
}

运行程序后,控制台输出对象信息,可以看到从ioc容器中拿出的对象已经成功被注解赋值

备注

内置注解

@Override:定义在java.lang.Override中,此注释只适用于修辞方法,表示一个方法声明打算重写超类中的另一个方法声明.

@Deprecated:定义在java.lang.Deprecated中,此注释可以用于修辞方法,属性,类,表示不鼓励程序员使用这样的元素,通常是因为它很危险或者存在更好的选择.

@SuppressWarnings:定义在java.lang.SuppressWarnings中,用来抑制编译时的警告信息.口与前两个注释有所不同,你需要添加一个参数才能正确使用,这些参数都是已经定义好了的,我们选择性的使用就好了.

  • @SuppressWarnings ("all")
  • @SuppressWarnings ("unchecked")
  • @SuppressWarnings (value={"unchecked","deprecation"})
  • 等等……

4个元注解

元注解的作用就是负责注解其他注解,Java定义了4个标准的meta-annotation类型,他们被用来提供对其他annotation类型作说明.
这些类型和它们所支持的类在java.lang.annotation包中可以找到

@Target:用于描述注解的使用范围(即:作用域,被描述的注解可以用在什么地方)

@Target(value = {ElementType.TYPE,ElementType.CONSTRUCTOR})
@Target(value = ElementType.TYPE)
@Target(ElementType.TYPE)

类,接口(包括注释类型)或枚举声明
  TYPE

字段声明(包括枚举常量)
  FIELD

方法声明
  METHOD

形式参数声明
  PARAMETER

构造声明
  CONSTRUCTOR

局部变量声明
  LOCAL_VARIABLE

注解类型声明
  ANNOTATION_TYPE

包声明
  PACKAGE

类型参数声明 @since 1.8
  TYPE_PARAMETER

使用类型 @since 1.8
  TYPE_USE

@Retention:表示需要在什么级别保存该注释信息,用于描述注解的生命周期 (SOURCE<CLASS<RUNTIME)

@Retention(value = RetentionPolicy.CLASS)
@Retention(RetentionPolicy.CLASS)

注解将被编译阶段丢弃
  SOURCE
注解将由编译器记录在类文件中,但VM不必在运行时保留它们。这是默认行为。
  CLASS
注解由编译器记录在类文件中,并在运行时由VM保留,因此可以通过反射方式读取它们
  RUNTIME

@Document:说明该注解将被包含在javadoc中

@lnherited:说明子类可以继承父类中的该注解

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • SpringBoot启动java.nio.charset.MalformedInputException: Input length = 1报错的解决方案

    SpringBoot启动java.nio.charset.MalformedInputException: I

    本文主要介绍了SpringBoot启动java.nio.charset.MalformedInputException: Input length = 1报错的解决方案
    2023-07-07
  • 最通俗的白话讲解JDK源码中的ThreadLocal

    最通俗的白话讲解JDK源码中的ThreadLocal

    ThreadLocal是JDK包提供的,它提供线程本地变量,如果创建一乐ThreadLocal变量,那么访问这个变量的每个线程都会有这个变量的一个副本,在实际多线程操作的时候,操作的是自己本地内存中的变量,从而规避了线程安全问题,感兴趣的朋友快来看看吧
    2022-01-01
  • Token登陆验证机制的原理及实现

    Token登陆验证机制的原理及实现

    这篇文章介绍了Token登陆验证机制的原理及实现,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-12-12
  • HttpClient详细使用示例代码

    HttpClient详细使用示例代码

    这篇文章主要介绍了HttpClient详细使用示例,包括导入依赖,使用工具类的详细代码,代码简单易懂,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-07-07
  • java 从int数组中获取最大数的方法

    java 从int数组中获取最大数的方法

    这篇文章主要介绍了java 从int数组中获取最大数的方法,需要的朋友可以参考下
    2017-02-02
  • Java日常练习题,每天进步一点点(61)

    Java日常练习题,每天进步一点点(61)

    下面小编就为大家带来一篇Java基础的几道练习题(分享)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧,希望可以帮到你
    2021-08-08
  • MyBatis XML方式的基本用法之多表查询功能的示例代码

    MyBatis XML方式的基本用法之多表查询功能的示例代码

    这篇文章主要介绍了MyBatis XML方式的基本用法之多表查询功能的示例代码,本文通过示例文字相结合的形式给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-07-07
  • 一文秒懂springboot druid 配置

    一文秒懂springboot druid 配置

    Druid是阿里巴巴开发的一个连接池,他提供了一个高效、功能强大、可扩展性好的数据库连接池,区别于hikari,今天通过本文给大家分享springboot druid 配置教程,需要的朋友参考下吧
    2021-08-08
  • 浅谈Mybatis乐观锁插件

    浅谈Mybatis乐观锁插件

    这篇文章主要介绍了浅谈Mybatis乐观锁插件,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-12-12
  • Spring Boot中如何使用断路器详解

    Spring Boot中如何使用断路器详解

    这篇文章主要给大家介绍了关于Spring Boot中如何使用断路器的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-08-08

最新评论