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();
}
}