一、JVM模型
java类的执行需要经历几个过程:
编译:*.java -> *.class
加载:类加载器根据一个类的全限定名来读取此类的二进制字节流到JVM内部,并存储在运行时内存区的方法区,然后将其转换为一个与目标类型对应的java.lang.Class对象实例
连接:
- 验证:校验格式(class文件规范),语义(final类是否有子类)
- 准备:静态变量赋初值和内存空间,final修饰的内存空间直接赋原值
- 解析:符号引用转化为直接引用,分配地址
初始化:有父类先初始化父类,然后初始化自己;将static修饰代码执行一遍,如果是静态变量,则用用户指定值覆盖原有初值;如果是代码块,则执行一遍操作。
二、反射
反射的过程发生在.class文件加载到jvm中,.class文件中包含java类的所有信息,在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,并且能改变它的属性。反射就是把java类中的各种成分映射成一个个的Java对象,并且可以进行操作。
反射获取class类实例的三种方式
- 1.对象.getClass();
-
利用对象调用getClass()方法获取对象的class实例
- 2.类名.class
- 3.class.forName(“权限定名”);
//第一种 getClass()
Class<? extends Student> skill1 = new Student().getClass();
//第二种 类名.class
Class skill2 = Student.class;
//第三种 权限定名
Class<?> skill3 = Class.forName("com.wyj.reflect.Student");
通过反射获取运行时类实现的接口和父类
//1.获取运行时类
Class<?> class1 = Class.forName("com.wyj.reflect.Student");
//2.获取接口
Class<?>[] interfaces = class1.getInterfaces();
for (Class c : interfaces) {
String cName = c.getName();
String cSimpleName = c.getSimpleName();
System.out.println(cName);
System.out.println(cSimpleName);
}
//3.获取父类
Class<?> superclass = class1.getSuperclass();
反射获取构造
Class<?> class1 = Class.forName("com.wyj.reflect.Student");
//获取构造
Constructor<?>[] constructors = class1.getConstructors();
for (Constructor constructor : constructors) {
//获取访问修饰符
int modifiers = constructor.getModifiers();
//将int类型修饰符转化为String
String string = java.lang.reflect.Modifier.toString(modifiers);
//获取访问名称
String name = constructor.getName();
//获取参数表
Class[] parameterTypes = constructor.getParameterTypes();
for (Class classType : parameterTypes) {
System.out.println(classType.getSimpleName());
}
System.out.println(string+" "+name);
}
System.out.println("================");
//获取指定参数的构造
Constructor<?> constructor = class1.getConstructor(String.class,int.class,String.class);
//创建对象
Student newStudent = (Student) constructor.newInstance("老王",35,"男");
System.out.println(newStudent);
反射获取成员变量
Class<? extends Student> class1 = student.getClass();
//获取全部属性(共有、私有)
Field[] fields = class1.getDeclaredFields();
//遍历每一个属性值
for (Field field : fields) {
field.setAccessible(true);//打破封装
//获取访问修饰符
int modifiers = field.getModifiers();
String modifier = Modifier.toString(modifiers);
//获取数据类型
Class<?> type = field.getType();
String simpleName = type.getSimpleName();
//获取属性名称
String name = field.getName();
//获取属性值
Object object = field.get(s);
System.out.println(modifier+" "+simpleName+" "+name+" "+object);
//设置属性值
if ("name".equals(name)) {
field.set(s,"老zhan");
}else if ("age".equals(name)) {
field.set(s,23);
}else if ("sex".equals(name)) {
field.set(s, "女");
}
System.out.println(s);
}
通过反射获取成员方法并使用
//获取运行时类
Class<?> class1 = Class.forName("com.wyj.reflect.Student");
//创建运行实例
Student student =(Student) class1.newInstance();
System.out.println("---------getDeclareMethods()---------");
Method[] methods = class1.getDeclaredMethods();
for (Method method : methods) {
//获取访问修饰符
int modifiers = method.getModifiers();
String modifier = Modifier.toString(modifiers);
//获取返回值类型
Class<?> returnType = method.getReturnType();
String returnTypename = returnType.getSimpleName();
//获取方法名称
String name = method.getName();
//获取参数列表
Class<?>[] parameterTypes = method.getParameterTypes();
for (Class<?> parameterType : parameterTypes) {
//获取简称
System.out.println(parameterType.getSimpleName());
}
System.out.println(modifier+" "+returnTypename+" "+name+" ");
//调用方法
if ("setName".equals(name)) {
method.invoke(student,"老y");
}
}
三、动态代理
为了解决静态代理的缺点,动态生成一个持有RealObject、并实现代理接口的Proxy,同时注入我们相同的扩展逻辑。
JDK动态代理 :只能代理实现接口的类,对没有实现接口的类不能实现JDK动态代理。哪怕你要代理的RealObject是不同的对象,甚至代理不同的方法,都可以动过动态代理,来扩展功能。
@return
* loader,指定当前目标对象使用类加载器,获取加载器的方法是固定的
* interfaces, 目标对象实现的接口的类型,使用泛型方式确认类型
* h,事件处理,执行目标对象的方法时,会触发事件处理器的方法,会把当前执行目标对象的方法作为参数传入
private Object obj;
public UserProxy(Object obj) {
this.obj = obj;
}
public Object getProxyObject() {
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
method.invoke(obj, args);
return null;
}
});
}
CGLIB动态代理 : 不需要提供接口
需要被引用的类
public class CgLibClass {
public CgLibClass()
{
System.out.println("CgLibClass构造器");
}
/**
* CgLig 无法代理final修饰的方法
*/
public void sayHell0(){
System.out.println("hello CGLIB");
}
}
代理类
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.invoke.MethodHandleInfo;
import java.lang.reflect.Method;
public class CgLibDemo implements MethodInterceptor {
/**
*
* @param o cglib生成的代理对象
* @param method 被代理的对象方法
* @param objects 方法入参
* @param methodProxy 代理方法
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("前置方法");
Object object = methodProxy.invokeSuper(o, objects);
System.out.println("后置方法");
return object;
}
}
实现
import net.sf.cglib.proxy.Enhancer;
public class Main {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
//設置enhancer對象的父類
enhancer.setSuperclass(CgLibClass.class);
//设置Cglib回调对象
enhancer.setCallback(new CgLibDemo());
//创建代理对象
CgLibClass cgLibClass = (CgLibClass) enhancer.create();
//调用目标方法
cgLibClass.sayHell0();
}
}