Spring-Aop学习的前提——反射+动态代理——1

Aop的实现是依靠动态代理实现的,动态代理又依靠反射。所以先拿出一天时间回顾一下反射等相关知识。
类的加载
当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化。
1.加载
就是指将class文件读入内存,并为之创建一个Class对象。
任何类被使用时系统都会建立一个Class对象。
2.连接
验证 是否有正确的内部结构,并和其他类协调一致
准备 负责为类的静态成员分配内存,并设置默认初始化值
解析 将类的二进制数据中的符号引用替换为直接引用
3.初始化

类初始化的时机:
1.创建类的实例
2.访问类的静态变量,或者为静态变量赋值
3.调用类的静态方法
4.使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
初始化某个类的子类
5.直接使用java.exe命令来运行某个主类

类加载器
负责将.class文件加载到内在中,并为之生成对应的Class对象。
虽然我们不需要关心类加载机制,但是了解这个机制我们就能更好的理解程序的运行。
类加载器的组成
1.Bootstrap ClassLoader 根类加载器
也被称为引导类加载器,负责Java核心类的加载
比如System,String等。在JDK中JRE的lib目录下rt.jar文件中
2.Extension ClassLoader 扩展类加载器
负责JRE的扩展目录中jar包的加载。
在JDK中JRE的lib目录下ext目录
3.Sysetm ClassLoader 系统类加载器
负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径(自己写的类)

反射:
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.
获取Class文件的三种方式
1.Object中的getClass()方法

Person person = new Person();
        Class c = person.getClass();

2.数据类型的静态属性class

Class c3 = Person.class;

3..Class类中的静态方法
public static Class forName(String className)

Class c4 = Class.forName("Reflect.Person"); //带包的全路径

以上三中方式都可以获得Class字节码文件,开发时候用第三种 Class.forName。因为第三种是一个字符串,而不是具体的类名,这样我们可以把字符串配到配置文件里

接下来我们看一下如何通过反射获取构造方法并使用
新建Person类:

package Reflect;

public class Person {
    private String name;
    private int age;
    private String address;
    public Person() {
        // TODO Auto-generated constructor stub
    }
    public Person(String name,int age) {
        this.name = name;
        this.age = age;
    }
    public Person(String name, int age, String address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }
    public void show() {
        System.out.println("show........");
    }
    public void method(String s) {
        System.out.println("method  "+s);
    }
    public String getString(String s,int i) {
        return s+"==="+i;
    }
    private void function() {
        System.out.println("function");
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + ", address=" + address + "]";
    }


}

首先获取Person字节码文件:

        //获取字节码文件
Class c4 = Class.forName("Reflect.Person"); //带包的全路径

通过getConstructors();获取所有public 修饰的构造函数

Constructor[] constructors = c4.getConstructors();
        for (Constructor con : constructors) {
            System.out.println(con);
        }

通过getDeclaredConstructors获取所有的构造函数

        //获取全部的构造方法 
Constructor[] constructors2 = c4.getDeclaredConstructors();
        for (Constructor con1 : constructors2) {
            System.out.println(con1);
        }

获取单个构造函数(分为有参数的构造器和无参数的构造器)
获取无参的构造器:

Constructor c1 = c4.getConstructor();//返回的构造方法对象(无参)
Object object = c1.newInstance();//相当于Person p = new Person();
System.out.println(object);

获取有参数的构造器:

//获取有参数的构造函数
Constructor con = c4.getConstructor(String.class,int.class,String.class);
Object obj  = con.newInstance("张三",34,"济南"); //通过带参构造方法对象创建对象
System.out.println(obj);

注意getConstructor的参数是Class。需要获得各参数的Class

猜你喜欢

转载自blog.csdn.net/qq_39411208/article/details/81561900