反射
String——>类——>对象
设计一个方法 给你一个字符串(包名加类名) 返回一个对象 对象里面还有属性值
我们之前做过的 考试系统的Question类 银行系统Person类
Question类和Person类都是自己定义的 这两个类的目的仅仅是为了存储某些信息
看似是个对象 更像是个容器 ——> 实体domain
传递一个字符串 帮我们创建对象 这样就不用自己创建 同时还能给对向内的所有属性赋值
——> Spring开源框架 IOC控制反转 DI依赖注入
AOP面向切面
IOC控制反转 Inversion of Control 对象的控制权反转
DI依赖注入 Dependency Injection 对象的控制权是别人的 别人在创建对象的同时 帮我们自动的注入属性值
DI是IOC的一个具体体现 需要先把控制权交给别人 如果别人做的好 可能才会帮你注入属性值 但是也可以不注入 所以DI的前提是先有IOC
自定义注解MyAnnotation:
@Target({ElementType.FIELD,ElementType.METHOD,ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String[] value();
}
Person类:
public class Person {
private String name;
private Integer age;
private String sex;
@MyAnnotation({"小兰","18","女"})
public Person(){}
public void setName(String name){
this.name = name;
}
public void setAge(Integer age){
this.age = age;
}
public void setSex(String sex){
this.sex = sex;
}
public String getName(){
return this.name;
}
public Integer getAge(){
return this.age;
}
public String getSex(){
return this.sex;
}
}
MySpring:
public class MySpring {
//设计一个方法 给一个类名 返回一个对象 并给这个对象属性赋值
public Object getBean(String className){
Object obj = null;
try {
//1.获取路径上所对应的类
Class clazz = Class.forName(className);
//2.获取类所对应的无参数构造方法 前提得有构造方法
Constructor con = clazz.getConstructor();
//3.通过构造方法得到当前类的对象
obj = con.newInstance();
//4.获取构造方法上对应的注解对象
Annotation ma = (MyAnnotation)con.getAnnotation(MyAnnotation.class);
//5.获取注解对象对应的类
Class mClazz = ma.getClass();
//6.获取注解对象里的value方法
Method m = mClazz.getMethod("value");
//7.执行value方法 并接收注解信息 注意value方法是属于注解的
String[] values = (String[]) m.invoke(ma);
//8.获取类中的全部的私有属性
Field[] fields = clazz.getDeclaredFields();
//9.构造出set+属性名的方法 并 运行给属性赋值
for(int i = 0;i<fields.length;i++){
//9.构造出set+属性名的方法 并 运行给属性赋值
//9.1 属性名首字母大写
String firstLetter = fields[i].getName().substring(0,1).toUpperCase();
String otherLetters = fields[i].getName().substring(1);
//9.2 利用StringBuilder拼接方法名
StringBuilder setMethodName = new StringBuilder("set");
setMethodName.append(firstLetter);
setMethodName.append(otherLetters);
//10.因为属性的方法需要传与属性类型相对应的参数类型 所以获取方法的参数类型 即获取属性的类型
Class fieldType = fields[i].getType();
//11.通过 拼接好的属性方法名 以及 方法参数类型 找到类中对应的set方法
Method fieldMethod = clazz.getMethod(setMethodName.toString(),fieldType);
//12.执行set方法 并 给方法传参 参数即为注解里的信息
//但是获取到的values信息都是String类型的 而属性不一定都是String类型的
//所以 需要将 String--->属性对应的类型
//fieldType.getConstructor(String.class).newInstance(values[i]) 利用这个构造方法来创建对象
//即先找到属性类型对应的构造方法 这个构造方法中有带String参数的
// (八个包装类中只有Character没有带String类型的构造方法 所以可以单独判断)
fieldMethod.invoke(obj,fieldType.getConstructor(String.class).newInstance(values[i]));
}
} catch (Exception e) {
e.printStackTrace();
}
return obj;
}
}
主方法:
public static void main(String[] args) {
MySpring ms = new MySpring();
Person p = (Person) ms.getBean("test_annotation.Person");//包名加类名
System.out.println(p.getName()+"--"+p.getAge()+"--"+p.getSex());
}