Bootstrap

java综合

反射相关

类的加载机制

classLoader(双亲委派)加载部分.class->类信息放入元空间->生成唯一Class对象放进堆内存

反射

目的:代码执行时,能够获取类的方法名、属性,以及给属性赋值

原理:Class对象相当于元空间的类信息的镜像,new直接通过元空间的类对象(有指针指向元空间类信息),反射是通过镜像生成对象。

实现:

public class Animal {
   //default 子类不可跨包, protect可以子类可跨包, private子类可以继承
    public float run(float distance){
   
       return  distance;
    }
}
public class Main {
   
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
   
        Animal animal1 = new Animal();
        animal1.run(2);

        //类的反射对象
        Class clz = Class.forName("Animal");
        //方法的反射对象
        Method method = clz.getMethod("run", float.class);
        //构造方法的反射对象
        Constructor constructor = clz.getConstructor();

        //通过反射实例化对象
        Object object = constructor.newInstance();
        //通过放射调用方法
        Object distance = method.invoke(object, 3);
    }
}

三种获取Class的方式

  1. 类全限定名获取:Class class = Class.forName(“com.xxxx.xx”);
  2. 具体类获取:Class class = 类.Class;
  3. 对象获取:Class class=object.getClass();

参考:https://www.bilibili.com/video/BV13q4y1s7U8?spm_id_from=333.337.search-card.all.click&vd_source=ccd2ca4db2c7f66c6f0ab6dd058b6208

动态代理

目的:想在所有被代理的方法前加一个方法,动态代理可以方便实现

原理:所有实现被代理对象的方法,都会转为执行invoke中的方法

实现:类似aop

注解

原理:注解只是一个标志,反射查看类信息时发现注解就进行相应操作。

实现:

1.使用Spring中定义好的注解

定义类,使用注解注册以及赋值

@Component
@Data
public class Student {
   
    @Value("小明")
    private String name;
    @Value("18")
    private int age;
}

定义配置,扫描包范围

@Configuration
@ComponentScan("com.test.bean")
public class MainConfiguration {
   
}

打印类信息

public class Main {
   
    public static void main(String[] args) {
   
        ApplicationContext context = new AnnotationConfigApplicationContext(MainConfiguration.class);
        System.out.println(context.getBean(Student.class));

    }
}

结果

Student(name=小明, age=18)

2.自定义注解实现@Component(spring工厂)以及@Value(spring依赖注入)

注解定义-》注解使用-》@MyComponent表示通过反射生成对象@MyValue表示通过反射赋值(更改属性权限)

注解定义

@Retention(RetentionPolicy.RUNTIME) //运行时使用
@Target(ElementType.TYPE)   //作用于类上
public @interface MyComponent {
   
}
@Retention(RetentionPolicy.RUNTIME) //运行时使用
@Target(ElementType.FIELD) //作用于属性上
public @interface MyValue {
   
    String value(); //放置给的属性值
}

类更改为自己的注解

@MyComponent
public class Student {
   
    @MyValue("小明")
    private String name;
    @MyValue("18")
    private int age;
}

寻找@MyComponet

Class<Student> studentClass = Student.class;
MyComponent myComponent = studentClass.getAnnotation(MyComponent.class);//这里开始只有类,只能找类注解,属性注解需要获取属性后,再获取属性上的注解

实现@MyComponent的方法

if(myComponent!=null){
   
   Constructor<Student> constructor = studentClass.getConstructor(null);
   Student student = constructor.newInstance();
}

寻找@MyValue

Field[] declareFields = studentClass.getDeclaredFields();// getFields()只能获取公有属性,getDeclaredFields()获取所有属性
for(Field field : declareFields){
   
    MyValue myValue = studentClass.getAnnotation(MyValue.class);
}

实现@MyValue的方法

if(myValue != null){
   
     declareField.setAccessible(true); // 变量为private,需要修改属性权限
    // 如果注解中的值为int需要进行转换
    if(declareField.getType().getName().equals("int")){
   
        declareField.set(student, Integer.parseInt(myValue.value()));//将注解中的值,赋值给创建出的目标对象
    }
    else{
   
        declareField.set(student, myValue.value());//将注解中的值,赋值给创建出的目标对象
    }
}

完整的测试类

public class Test {
   
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
   
        Class<Student> studentClass = Student.class;
        MyComponent myComponent = studentClass.getAnnotation(MyComponent.class);
        if(myComponent!=null){
   
           Constructor<Student> constructor = studentClass.getConstructor(null);
           Student student = constructor.newInstance();

           Field[] declareFields = studentClass.getDeclaredFields();// getFields()只能获取公有属性,getDeclaredFields()获取所有属性
           for(Field declareField : declareFields){
   
               MyValue myValue = declareField.getAnnotation(MyValue.class);//属性注解,就要在属性上去寻找
               if(myValue != null){
   
                    declareField.setAccessible(true); // 变量为private,需要修改属性权限
                   // 如果注解中的值为int需要进行转换
                   if(declareField.getType().getName().equals("int")){
   
                       declareField.set(student, Integer.parseInt(myValue.value()));//将注解中的值,赋值给创建出的目标对象
                   }
                   else{
   
                       declareField.set(student, myValue.value());//将注解中的值,赋值给创建
;