Java--反射

public class TestRef {
	
	@Test
	public void test1() throws Exception {
		
		Class<Person> clazz = Person.class;
		// 创建p对应运行时类Person对象
		Person person = clazz.newInstance();
		
		Field f1 = clazz.getField("name");
		f1.set(person, "xiaowang");
		
		// age 是私有的,需要这么写
		Field  f2 = clazz.getDeclaredField("age");
		f2.setAccessible(true);
		f2.set(person, 20);
		System.out.println(person);
		
		// 调用类的方法
		Method m1 = clazz.getMethod("set",String.class);
		m1.invoke(person,"xiaobai");
		
		
	}
}

java.lang.Class 反射的源头;
这里写图片描述
当创建一个类,通过javac编译生成对应的class文件,之后我们使用java.exe加载此class文件,此class文件加载到内存以后,就是一个运行时类。存在缓存区,那么这个运行时类本身就是一个Class。
1)创建对应运行时类的对象
2)获取对应的运行时类的完整结构(属性,方法,构造器。。。)
3)调用对应的运行时类的指定的结构(属性,方法,构造器。。。)
4)动态代理

获取Class的实例

	public void test2() throws Exception {
		
		// 1. 调用运行时类本身的.class 属性
		Class clazz1 = Person.class;
		
		// 2. 通过运行时类的对象获取
		Person p = new Person();
		Class clazz2 = p.getClass();
		
		// 3. 通过Class的静态方法获取
		String className = "com.atguigu.test.Person";
		Class clazz3 = Class.forName(className);
		
		// 4. 通过类加载器
		ClassLoader classLoader = this.getClass().getClassLoader();
		Class clazz4 = classLoader.loadClass(className);
	}

类的加载过程
当程序主动使用某个类时,如果该类还未被加载到内存中,则系统会通过如下三个步骤来对该类进行初始化。
1、类的加载:将类的class文件读入内存,并为之创建一个java.lang.Class对象。此过程由类加载器完成;
2、类的连接:将类的二进制数据合并到JRE中;
3、类的初始化:JVM负责对类进行初始化;
ClassLoader
引导类加载器:用C++编写的,是JVM自带的类加载器,负责Java平台核心库,用来加载核心类库。该加载器无法直接获取
扩展类加载器:负责jre/lib/ext目录下的jar包或 –D java.ext.dirs 指定目录下的jar包装入工作库
系统类加载器:负责java –classpath 或 –D java.class.path所指的目录下的类与jar包装入工作 ,是最常用的加载器

newInstance()实际上就是调用运行时类的无参构造器,要求运行时类有空参构造器,构造器权限足够。

public void test3() throws Exception {
		Class clazz = Person.class;
		Field[] fe = clazz.getDeclaredFields();
		for(Field f : fe) {
			// 获取属性权限修饰符
			int i =f.getModifiers();
			String str = Modifier.toString(i);
			System.out.print(str+" ");
			
			// 获取属性的类型
			Class type = f.getType();
			System.out.println(type.getName());
		}	
			// 获取运行时类及父类所有声明public方法
			Method[] m1 = clazz.getMethods();
			// 获取运行时类本身声明的所有方法
			Method[] m2 = clazz.getDeclaredMethods();
			for(Method m : m2) {
				// 1、获取注解
				Annotation[] arr = m.getAnnotations();
				// 2、获取权限修饰符
				String sttr = Modifier.toString(m.getModifiers());
				// 3、获取返回值类型
				Class returnType = m.getReturnType();
				// 4、获取方法名
				String name = m.getName();
				// 5、获取形参列表
				Class[] pram = m.getParameterTypes();
				// 6、获取异常类型
				Class[] exce = m.getExceptionTypes();
			}
			
			Class clazz1 = Person.class;
			// 获取运行时的父类
			Class superClass = clazz1.getSuperclass();
			// 获取带泛型的父类
			Type type1 = clazz1.getGenericSuperclass();
			// 获取父类的泛型
			ParameterizedType parm = (ParameterizedType)type1;
			Type[] ars = parm.getActualTypeArguments();
			System.out.println(((Class)ars[0]).getName());
			// 获取实现的接口
			Class[] inter = clazz1.getInterfaces();
			// 获取所在的包
			Package pack = clazz1.getPackage();
			// 获取注解
			Annotation[] anns = clazz1.getAnnotations();
public void test4() throws Exception {
		Class clazz = Person.class;
		Person p = (Person) clazz.newInstance();
		// 操作属性
		// public 的属性
		Field fieldName = clazz.getField("name");
		fieldName.set(p, "xiaohong");
		// private 的属性,必须设置为true
		Field  f = clazz.getDeclaredField("age");
		f.setAccessible(true);
		f.set(p,10);
		
		//调用方法
		Method me = clazz.getMethod("add", int.class,int.class);
		int sum = (int) me.invoke(p, 10,11);
		System.out.println(sum);
		
		// 调用静态方法
		Method me2 = clazz.getDeclaredMethod("sub", int.class,int.class);
		int sub = (int) me2.invoke(Person.class, 12,10);
		System.out.println(sub);
		
		// 调用构造器
		String str = "com.atguigu.test.Person";
		Class clazz2 = Class.forName(str);
		Constructor con = clazz2.getDeclaredConstructor(String.class,int.class);
		con.setAccessible(true);
		Person per = (Person) con.newInstance("xiaowang",11);
		System.out.println(per);
		
		
		Class clazz3  = Person.class;
		Person person = (Person) clazz3.newInstance();
		Method m3 = clazz3.getMethod("test1");
		m3.invoke(person);
		
	}

代理设计模式的原理:
使用一个代理将对象包装起来, 然后用该代理对象取代原始对象. 任何对原始对象的调用都要通过代理. 代理对象决定是否以及何时将方法调用转到原始对象上

静态代理:
要求被代理类和代理类同时实现相应的一套接口;通过被代理类的对象调用重写接口的方法时,实际上执行的是被代理类的同样的方法的调用;
动态代理:
在程序运行时,根据被被代理类及其实现的接口,动态的创建一个代理类。当调用代理类的实现的抽象方法时,就发起对被代理同样方法的调用

2、提供一个实现了InvocationHandler接口实现类,并重写invoke方法。
1、Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), h);
注:obj时被代理对象:h实现了InvocationHandler接口的实现类

package com.atguigu.test;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

// 动态代理的使用
interface Subject{
	void action();
}

// 被代理类
class RealSubject implements Subject{

	@Override
	public void action() {
		System.out.println("被代理类执行========");		
	}
	
}

class MyInvo implements InvocationHandler{
	Object obj; // 实现了接口的被代理类的对象声明
	// 1 给被代理的对象实例化 2 返回一个代理类对象
	public Object build(Object obj) {
		this.obj = obj;
		return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
	}
	
	// 当通过代理类的对象发起对重写的方法的调用时,会转化为对如下的invoke方法的调用
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object returnVal = method.invoke(obj, args);
		return returnVal;
	}
	
}


public class TestProxy {
	public static void main(String[] args) {
		
		// 1 创建一个被代理类对象
		RealSubject re = new RealSubject();
		// 2 创建一个实现了InvocationHandler接口的类的对象
		MyInvo handler = new MyInvo();
		// 3 调用build方法,动态返回一个同样实现了re所在类实现的接口Subject的代理类的对象
		Object obj = handler.build(re);
		Subject sub = (Subject)obj;
		
		sub.action();
	}

}


// 动态代理和AOP

package com.atguigu.test;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

interface Humen {

	void info();

	void fly();
}

class SuperMen implements Humen {

	public void info() {
		System.out.println("i am superMen");
	}

	public void fly() {
		System.out.println("i can fly");
	}

}

class HumenUtil {
	public void method1() {
		System.out.println("=======11111========");
	}

	public void method2() {
		System.out.println("=======22222=======");
	}
}

class MyInvocationHandler implements InvocationHandler {
	Object obj;

	public void setObject(Object obj) {
		this.obj = obj;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		HumenUtil hu = new HumenUtil();
		hu.method1();
		Object returnVal = method.invoke(obj, args);
		hu.method2();
		return returnVal;
	}

}

// 动态创建一个代理类
class MyProxy {
	public static Object getProxyInstance(Object obj) {
		MyInvocationHandler he = new MyInvocationHandler();
		he.setObject(obj);

		return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
				obj.getClass().getInterfaces(), he);
	}

}

public class TestAop {
	public static void main(String[] args) {
		SuperMen men = new SuperMen();// 创建一个被代理类的对象
		Object obj = MyProxy.getProxyInstance(men);//返回一个代理类的对象
		Humen hu = (Humen)obj;
		hu.info();//通过代理类的对象调用重写的抽象方法
		
		hu.fly();
		
	}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值