反射
    String——>类——>对象
    设计一个方法 给你一个字符串(包名加类名) 返回一个对象 对象里面还有属性值

    我们之前做过的 考试系统的Question类 银行系统Person类
    Question类和Person类都是自己定义的 这两个类的目的仅仅是为了存储某些信息
    看似是个对象 更像是个容器 ——> 实体domain

    传递一个字符串 帮我们创建对象 这样就不用自己创建 同时还能给对向内的所有属性赋值
    ——> Spring开源框架 IOC控制反转 DI依赖注入
    AOP面向切面
    IOC控制反转 Inversion of Control 对象的控制权反转
    DI依赖注入 Dependency Injection 对象的控制权是别人的 别人在创建对象的同时 帮我们自动的注入属性值
    DI是IOC的一个具体体现 需要先把控制权交给别人 如果别人做的好 可能才会帮你注入属性值 但是也可以不注入 所以DI的前提是先有IOC

    自定义注解MyAnnotation:

    1. @Target({ElementType.FIELD,ElementType.METHOD,ElementType.CONSTRUCTOR})
    2. @Retention(RetentionPolicy.RUNTIME)
    3. public @interface MyAnnotation {
    4. String[] value();
    5. }

    Person类:

    1. public class Person {
    2. private String name;
    3. private Integer age;
    4. private String sex;
    5. @MyAnnotation({"小兰","18","女"})
    6. public Person(){}
    7. public void setName(String name){
    8. this.name = name;
    9. }
    10. public void setAge(Integer age){
    11. this.age = age;
    12. }
    13. public void setSex(String sex){
    14. this.sex = sex;
    15. }
    16. public String getName(){
    17. return this.name;
    18. }
    19. public Integer getAge(){
    20. return this.age;
    21. }
    22. public String getSex(){
    23. return this.sex;
    24. }
    25. }

    MySpring:

    1. public class MySpring {
    2. //设计一个方法 给一个类名 返回一个对象 并给这个对象属性赋值
    3. public Object getBean(String className){
    4. Object obj = null;
    5. try {
    6. //1.获取路径上所对应的类
    7. Class clazz = Class.forName(className);
    8. //2.获取类所对应的无参数构造方法 前提得有构造方法
    9. Constructor con = clazz.getConstructor();
    10. //3.通过构造方法得到当前类的对象
    11. obj = con.newInstance();
    12. //4.获取构造方法上对应的注解对象
    13. Annotation ma = (MyAnnotation)con.getAnnotation(MyAnnotation.class);
    14. //5.获取注解对象对应的类
    15. Class mClazz = ma.getClass();
    16. //6.获取注解对象里的value方法
    17. Method m = mClazz.getMethod("value");
    18. //7.执行value方法 并接收注解信息 注意value方法是属于注解的
    19. String[] values = (String[]) m.invoke(ma);
    20. //8.获取类中的全部的私有属性
    21. Field[] fields = clazz.getDeclaredFields();
    22. //9.构造出set+属性名的方法 并 运行给属性赋值
    23. for(int i = 0;i<fields.length;i++){
    24. //9.构造出set+属性名的方法 并 运行给属性赋值
    25. //9.1 属性名首字母大写
    26. String firstLetter = fields[i].getName().substring(0,1).toUpperCase();
    27. String otherLetters = fields[i].getName().substring(1);
    28. //9.2 利用StringBuilder拼接方法名
    29. StringBuilder setMethodName = new StringBuilder("set");
    30. setMethodName.append(firstLetter);
    31. setMethodName.append(otherLetters);
    32. //10.因为属性的方法需要传与属性类型相对应的参数类型 所以获取方法的参数类型 即获取属性的类型
    33. Class fieldType = fields[i].getType();
    34. //11.通过 拼接好的属性方法名 以及 方法参数类型 找到类中对应的set方法
    35. Method fieldMethod = clazz.getMethod(setMethodName.toString(),fieldType);
    36. //12.执行set方法 并 给方法传参 参数即为注解里的信息
    37. //但是获取到的values信息都是String类型的 而属性不一定都是String类型的
    38. //所以 需要将 String--->属性对应的类型
    39. //fieldType.getConstructor(String.class).newInstance(values[i]) 利用这个构造方法来创建对象
    40. //即先找到属性类型对应的构造方法 这个构造方法中有带String参数的
    41. // (八个包装类中只有Character没有带String类型的构造方法 所以可以单独判断)
    42. fieldMethod.invoke(obj,fieldType.getConstructor(String.class).newInstance(values[i]));
    43. }
    44. } catch (Exception e) {
    45. e.printStackTrace();
    46. }
    47. return obj;
    48. }
    49. }

    主方法:

    1. public static void main(String[] args) {
    2. MySpring ms = new MySpring();
    3. Person p = (Person) ms.getBean("test_annotation.Person");//包名加类名
    4. System.out.println(p.getName()+"--"+p.getAge()+"--"+p.getSex());
    5. }