package anno;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
/**
* @program: tx_annotation_demo
* @description: 使用反射机制模拟实现IOC(控制反转)
* @author: czg
* @create: 2019-09-27 22:41
*/
public class MySpring {
public static void main(String[] args) {
//题目:入参:一个包名.类名字符串 出参:一个对应的对象 对象中已存在数据(数据存在无参构造方法的注解中)
Person p=(Person)Ioc("anno.Person");
System.out.println(p.toString());
}
public static Object Ioc(String ClassName){
Object o =null;
try {
Class clazz=Class.forName(ClassName);
//获得对象
o = clazz.newInstance();
//获得无参构造方法
Constructor constructor = clazz.getConstructor();
System.out.println("--------------开始获得注解中的数据---------------");
//获得无参构造方法上面的自定义注解
Annotation annotation = constructor.getAnnotation(MyAnnotaion.class);
//获得注解类的Class
Class aClass = annotation.getClass();
//获得注解类的方法
Method test = aClass.getMethod("test");
//获得其里面的数据
String[] data =(String[]) test.invoke(annotation);
System.out.println("注解中的数据:"+Arrays.toString(data));
System.out.println("--------------构建组合对象set方法:set+大写首字母的对象属性名---------------");
//构建组合Object所代表对象中的setXxxx方法
//获得私有的属性
Field[] fields = clazz.getDeclaredFields();
//循环遍历属性名
for (int i=0;i<fields.length;i++){
Field field=fields[i];
String name = field.getName();
//组合属性对应的set方法
StringBuilder setMethod=new StringBuilder("set").append(name.substring(0,1).toUpperCase())
.append(name.substring(1));
//获得属性的类型
Class filedType=field.getType();
//获得并运行set方法
Method method = clazz.getMethod(setMethod.toString(),filedType);
//需要将注解读取到的String字符串转出其他对应的类型
//Integer i=new Integer("");
//找到属性类型对应待String类型的构造函数 构造出新的对象
method.invoke(o,filedType.getConstructor(String.class).newInstance(data[i]));
}
} catch (Exception e) {
e.printStackTrace();
}
return o;
}
}
package anno;
/**
* @program: tx_annotation_demo
* @description: 自定义注解测试使用
* @author: czg
* @create: 2019-09-27 21:54
*/
public class Person {
//@MyAnnotaion(test = {"czg","18","男"})
private String name;
private Integer age;
private String sex;
@MyAnnotaion(test = {"czg","18","男"})
public Person() {
}
public Person(String name, Integer age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
'}';
}
}
package anno;
import java.lang.annotation.*;
/**
* @program: tx_annotation_demo
* @description:
*
* 自定义注解(与接口用法有点类似)
* 特点:注解中的方法必须有返回值,返回值必须是以下五种
* 基本数据类型 String类型 枚举类型enum 注解类型@ 数组类型(数组内部必须是前面四种)
*
* 注解要使用还必须使用Java提供好的元注解(元注解:元注解不是拿来使用的,是用来辅助说明自定义注解的)
*
* 常见元注解有:@Target 说明声明的注解是放在哪里使用的(注解一般放在 类的上面,属性上面,方法的上面,构造方法的上面,参数前面)
* ElementType.FIELD(属性上面),ElementType.METHOD(方法上面),ElementType.CONSTRUCTOR(构造方法上面) 注解可以在
* @Retention 描述当前的这个注解存在什么作用域中 SOURCE:源码文件 CLASS:字节码文件 RUNTIME:内存运行
* @Inherited 描述当前这个注解是否会被子类对象继承
* @Documented 描述当前这个注解是否能生成文档
* @author: czg
* @create: 2019-09-27 20:50
*/
@Target({ElementType.FIELD,ElementType.METHOD,ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotaion {
public static final String NAME_TEST="XXXX";//一般注解里面比较少用这种
//public abstract 一般是默认的
public abstract String[] test();
}