反射机制概述
反射是被视为动态语言的关键, 反射机制允许程序在执行期借助反射API取得任何类的内部信息,并能直接操作任意对象的内部属性和方法;
java文件编译为.class文件后,由类加载器加载后,在堆内存的方法区中就产生了一个一个的Class类型的实例对象,一个类只能有一个Class实例,这个对象实例就包含了完整的类的结构信息.可以通过这个对象实例看到类的结构
Class类实例的获取
Class类实例只能从内存中获取, 无法主动实例化, 因为在.class字节文件被加载至内存时, 就会实例化每一个类的Class实例对象.且一个类只会实例化一个Class对象;
类,接口,数组,注解,枚举,数组,基本数据类型,void都能获取到Class的实例;
public class ReflectionTest {
@Test
public void test1() throws Exception {
// 使用各类直接获取
Class<Person> clazz = Person.class;
System.out.println(clazz);
// 使用类的实例调用getClass()方法获取
Person p = new Person();
Class<? extends Person> clazz1 = p.getClass();
System.out.println(clazz1);
// 使用Class.forName(String)方法获取
Class<?> clazz2 = Class.forName("com.bryan.study.reflect.Person");
System.out.println(clazz2);
// 使用类加载器获取
ClassLoader classLoader = ReflectionTest.class.getClassLoader();
Class<?> clazz3 = classLoader.loadClass("com.bryan.study.reflect.Person");
System.out.println(clazz3);
}
}
class Human {
private String color;
private String nation;
public String cameFrom(){
return this.nation;
}
}
@MyAnnotation
class Person extends Human implements Comparable<Person>{
@MyAnnotation
private String username;
private String password;
String mobile;
public int status;
public String interest;
public Person(){
}
public Person(String username, String mobile) {
this.username = username;
this.mobile = mobile;
}
private Person(String username, String mobile, String password, int status){
this.username = username;
this.mobile = mobile;
this.password = password;
this.status = status;
}
@MyAnnotation
public String work (String job, String boss) throws NullPointerException, ClassCastException{
System.out.println("打工人"+this.username+"正在为"+boss+"做"+job+"工作");
return job;
}
public static void eat(){
System.out.println("吃屎");
}
private void sleep(){
System.out.println("睡觉");
}
@Override
public String toString() {
return "Person{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", mobile='" + mobile + '\'' +
", status=" + status +
", interest='" + interest + '\'' +
'}';
}
@Override
public int compareTo(Person o) {
return 0;
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})
@interface MyAnnotation {
String value() default "hello";
}
类的加载过程以及类加载器ClassLoader
类加载器的作用是用来吧类(Class)装载进内存的, JVM规范定义了如下类型的类加载器:
1.Bootstrap Classloader: 引导类加载器,用C++编写的,是JVM自带的类加载器, 负责Java品台核心库,用来装载核心类库.该加载器无法直接获取;
2.Extesion Classloader: 扩展类加载器, 负责jre/lib/ext目录下的jar包或-D java.ext.dirs 指定目录下的jar包装入工作库;
3.System Classloader: 系统类加载器, 负责java -classpath或-D java.class.path所指的目录下的类与jar包装入工作, 是常用的加载器;
4.自定义加载器;
public class ReflectionTest {
@Test
public void loaderTest() {
// 获取系统类加载器 sun.misc.Launcher$AppClassLoader@18b4aac2
ClassLoader classLoader = ReflectionTest.class.getClassLoader();
System.out.println(classLoader);
// 获取扩展类加载器 sun.misc.Launcher$ExtClassLoader@372f7a8d
ClassLoader classLoaderParent = classLoader.getParent();
System.out.println(classLoaderParent);
// 无法获取 引导类加载器, 这里获取到的是null
ClassLoader bootstrapLoader = String.class.getClassLoader();
System.out.println(bootstrapLoader);
// 使用类加载器读取配置文件
InputStream is = classLoader.getResourceAsStream("db.properties");
Properties p = new Properties();
p.load(is);
String username = p.getProperty("username");
System.out.println(username);
}
}
创建运行时类的对象
何时会用到反射来实例化类的对象: 通常在编译前无法确认需要实例化的类是哪种类,只有在运行时才能确认需要实例化的类时, 才会用到反射来实例化类的对象; 这其实体现出了反射的动态性; 这也就是为什么许多框架底层大量运用了反射机制,利用反射的动态性来处理业务逻辑;
@Test
public void newTest() throws IllegalAccessException, InstantiationException {
Class<Person> clazz = Person.class;
// 需要运行时类提供足够权限的空参构造器, 否则会报IllegalAccessException,InstantiationException异常
Person person = clazz.newInstance();
System.out.println(person);
}
获取运行时类的完整结构
获取运行时类的属性以及部分源码分析
@Test
public void fieldTest() {
Class<Person> clazz = Person.class;
// 获取运行时类public修饰的属性以及其父类,接口public修饰的属性
Field[] fields = clazz.getFields();
// 获取运行时类所有的属性,无法获取其父类,接口的属性
Field[] declaredFields = clazz.getDeclaredFields();
for (Field field: declaredFields) {
// 获取属性的注解
Annotation[] annotations = field.getAnnotations();
for (Annotation a: annotations) {
System.out.println(a.annotationType().getName());
}
// 获取属性的修饰符
int modifiers = field.getModifiers();
System.out.print(Modifier.toString(modifiers)+"\t");
// 获取属性的类型
Class<?> type = field.getType();
System.out.print(type.getName()+"\t");
// 获取属性的名称
System.out.println(field.getName());
System.out.println();
}
}
/**源码解析*/
public final class Class<T> implements java.io.Serializable, GenericDeclaration, Type, AnnotatedElement {
....
@CallerSensitive
public Field[] getFields() throws SecurityException {
// 使得成员属性可访问
checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
return copyFields(privateGetPublicFields(null));
}
private Field[] privateGetPublicFields(Set<Class<?>> traversedInterfaces) {
checkInitted();
Field[] res;
// 尝试从缓存中获取属性
ReflectionData<T> rd = reflectionData();
if (rd != null) {
res = rd.publicFields;
if (res != null) return res;
}
// No cached value available; compute value recursively.
// Traverse in correct order for getField().
// 没有缓存, 则重新获取
List<Field> fields = new ArrayList<>();
if (traversedInterfaces == null) {
traversedInterfaces = new HashSet<>();
}
// Local fields
// 获取运行时类自己的所有属性传true表示只获取public修饰的属性
Field[] tmp = privateGetDeclaredFields(true);
addAll(fields, tmp);
// 递归调用 获取实现接口的属性
// Direct superinterfaces, recursively
for (Class<?> c : getInterfaces()) {
if (!traversedInterfaces.contains(c)) {
traversedInterfaces.add(c);
addAll(fields, c.privateGetPublicFields(traversedInterfaces));
}
}
// 递归调用 获取父类的属性
// Direct superclass, recursively
if (!isInterface()) {
Class<?> c = getSuperclass();
if (c != null) {
addAll(fields, c.privateGetPublicFields(traversedInterfaces));
}
}
res = new Field[fields.size()];
fields.toArray(res);
if (rd != null) {
rd.publicFields = res;
}
return res;
}
private Field[] privateGetDeclaredFields(boolean publicOnly) {
checkInitted();
Field[] res;
// 尝试从缓存中获取
ReflectionData<T> rd = reflectionData();
if (rd != null) {
res = publicOnly ? rd.declaredPublicFields : rd.declaredFields;
if (res != null) return res;
}
// No cached value available; request value from VM
// 获取属性信息并缓存至ReflectionData中
res = Reflection.filterFields(this, getDeclaredFields0(publicOnly));
if (rd != null) {
if (publicOnly) {
rd.declaredPublicFields = res;
} else {
rd.declaredFields = res;
}
}
return res;
}
....
}
获取运行时类的方法
@Test
public void methodTest(){
Class<Person> clazz = Person.class;
// 获取运行时类public修饰的方法以及其父类,接口public修饰的方法
Method[] methods = clazz.getMethods();
// 获取运行时类所有的方法,无法获取其父类,接口的方法
Method[] declaredMethods = clazz.getDeclaredMethods();
for (Method method: declaredMethods) {
// 获取方法的注解
Annotation[] annotations = method.getAnnotations();
for(Annotation a: annotations) {
System.out.println(a.toString());
}
// 获取方法的修饰符
int modifiers = method.getModifiers();
System.out.print(Modifier.toString(modifiers)+"\t");
// 获取方法的返回值
Class<?> returnType = method.getReturnType();
System.out.print(returnType.getName()+"\t");
// 获取方法名
String name = method.getName();
System.out.print(name);
System.out.print("(");
// 获取方法的参数
Class<?>[] parameterTypes = method.getParameterTypes();
for (int i = 0 ;i <= parameterTypes.length-1;i++) {
if (i == parameterTypes.length-1){
System.out.print(parameterTypes[i].getName()+" arg" + i);
break;
}
System.out.print(parameterTypes[i].getName()+" arg" + i+",");
}
System.out.print(")\t");
// 获取方法抛出的异常
Class<?>[] exceptionTypes = method.getExceptionTypes();
if (exceptionTypes.length>0) {
System.out.print("throws\t");
for (int j = 0 ;j <= exceptionTypes.length-1;j++) {
if (j == exceptionTypes.length-1){
System.out.print(exceptionTypes[j].getName()) ;
break;
}
System.out.print(exceptionTypes[j].getName()+",");
}
}
System.out.println();
System.out.println();
}
}
获取运行时类的构造器
@Test
public void constructorTest(){
Class clazz = Person.class;
// 获取运行时类的public修饰的构造器
Constructor[] constructors = clazz.getConstructors();
// 获取运行时类的所有构造器
Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
for (Constructor c: declaredConstructors) {
// 获取构造器修饰符
int modifiers = c.getModifiers();
// 获取构造器名称
String name = c.getName();
// 获取构造器参数
Class[] parameterTypes = c.getParameterTypes();
}
}
获取运行时类的其他结构
@Test
public void otherTest(){
Class<Person> clazz = Person.class;
Package pack = clazz.getPackage(); // 获取包名
Class<? super Person> superclass = clazz.getSuperclass(); // 获取父类
Class<?>[] interfaces = clazz.getInterfaces(); // 获取实现的接口
Annotation[] annotations = clazz.getAnnotations(); // 获取注解
}
调用运行时类的指定结构
@Test
public void invokeTest() throws IllegalAccessException, InstantiationException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException {
Class<Person> clazz = Person.class;
// 实例化
// Person person = clazz.newInstance();
// 获取空参构造器
Constructor<Person> constructor = clazz.getConstructor();
// 设置构造器可访问
constructor.setAccessible(true);
Person person = constructor.newInstance();
// 获取指定属性
Field username = clazz.getDeclaredField("username");
// 设置属性 username 可访问 以防止调用set方法时权限不够
username.setAccessible(true);
// 设置属性值 为实例对象person的username属性设置值 bryan
username.set(person, "bryan");
System.out.println(person);
// 获取指定的方法
Method work = clazz.getMethod("work", String.class, String.class);
// 设置方法可访问
work.setAccessible(true);
// 调用 work 方法 并返回方法的返回值
Object invoke = work.invoke(person, "编码", "Alex");
System.out.println(invoke);
}
动态代理
public class ProxyTest {
@Test
public void test(){
SuperMan s = new SuperMan();
HumanBean proxy = (HumanBean) ProxyFactory.getProxy(s);
proxy.work("编码", "Alex");
}
}
// 被代理類實現的接口
interface HumanBean {
public String eat();
public void work(String job, String boss);
}
// 被代理類
class SuperMan implements HumanBean{
@Override
public String eat() {
System.out.println("吃饭");
return "正在吃饭";
}
@Override
public void work(String job, String boss) {
System.out.println("打工人为"+boss+"做"+job+"工作");
}
}
// 代理工廠
class ProxyFactory {
public static Object getProxy(Object obj){
Class<?> clazz = obj.getClass();
MyHandler myHandler = new MyHandler(obj);
// 創建代理對象 需要 傳入被代理類的類加載器, 被代理類所實現的所有接口, 以及一個回調方法處理器
return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), myHandler);
}
}
// 回調方法處理器
class MyHandler implements InvocationHandler {
private Object obj;
public MyHandler() {
}
public MyHandler(Object obj) {
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 回調被代理類方法前可編寫公用的代碼模塊 處理與業務無關的事務, 解耦
// 在處理器中 回調被代理類的方法
Object invoke = method.invoke(this.obj, args);
System.out.println("动态代理invoke被调用");
// 回調被代理類方法后可編寫公用的代碼模塊 處理與業務無關的事務, 解耦
return invoke;
}
}