关于Java注解模拟spring ioc容器的案例
不懂关于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;}@Overridepublic 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:说明子类可以继承父类中的该注解
感谢你能够认真阅读完这篇文章,希望小编分享关于Java注解模拟spring ioc容器的案例内容对大家有帮助,同时也希望大家多多支持亿速云,关注亿速云行业资讯频道,遇到问题就找亿速云,详细的解决方法等着你来学习!
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。