阅读更多
package com.midea.common.classTest;
public class ClassModelTest {
// 执行顺序大致分类:
// 1.静态属性,静态方法声明,静态块。
// 2.动态属性,普通方法声明,构造块。
// 3.构造方法。
// 当再次创建一个对象,不再执行静态部分,仅仅重复执行普通部分。
// 一切都是先父类再子类(因为子类的static初始化可能会依赖于父类成员能否被正确初始化)
// 类加载先初始静态变量,后是静态方法
public static String name = "luoxn28";
private String age;
public String sex;
// 类加载时会调用静态方法
static {
System.out.println("静态块");
}
public ClassModelTest() {
System.out.println("构造方法");
}
public static String getName() {
return name;
}
public void setName(String name) {
ClassModelTest.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "ClassModelTest [name=" + name + ", age=" + age + ", sex=" + sex + "]";
}
public void sayHello(String value) {
System.out.println("sayHello方法 value == " + value);
}
}
package com.midea.common.classTest;
public interface Subject {
public void rent();
public void hello(String str);
}
package com.midea.common.classTest;
public class RealSubject implements Subject {
@Override
public void rent() {
System.out.println("I want to rent my house");
}
@Override
public void hello(String str) {
System.out.println("hello: " + str);
}
}
package com.midea.common.classTest;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;
public class DynamicProxy implements InvocationHandler {
// 这个就是我们要代理的真实对象
private Object subject;
// 构造方法,给我们要代理的真实对象赋初值
public DynamicProxy(Object subject) {
this.subject = subject;
}
public DynamicProxy() {
super();
// TODO Auto-generated constructor stub
}
// 绑定委托对象,并返回代理类
public Object bind(Object tar) {
this.subject = tar;
// 绑定该类实现的所有接口,取得代理类
return Proxy.newProxyInstance(tar.getClass().getClassLoader(), tar.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object object, Method method, Object[] args) throws Throwable {
// 在代理真实对象前我们可以添加一些自己的操作
System.out.println("before rent house");
System.out.println("Method:" + method);
// 当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
method.invoke(subject, args);
// 在代理真实对象后我们也可以添加一些自己的操作
System.out.println("after rent house");
return null;
}
}
package com.midea.common.classTest;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.Proxy;
import org.apache.commons.cli.GnuParser;
import org.yaml.snakeyaml.Yaml;
public class ClassTest {
public static void main(String args[]) throws ClassNotFoundException, InstantiationException,
IllegalAccessException, IntrospectionException, IllegalArgumentException, InvocationTargetException {
// =============================Class.forName
Class clazz = Class.forName("com.midea.common.classTest.ClassModelTest"); // 要求JVM查找并加载指定的类,返回的是一个类(类信息)
System.out.println("clazz == " + clazz.getName()); // clazz ==
// com.midea.common.classTest.ClassModelTest
// newInstance(),用于以类实例化一个实例
// ClassModelTest classModelTest =
// (ClassModelTest)Class.forName("com.midea.common.classTest.ClassModelTest").newInstance();与
// ClassModelTest classModelTest = new ClassModelTest() 是一样的效果
// newInstance()主要是为了考虑到软件的可伸缩、可扩展和可重用等软件设计思想,如按配置文件实现对象的实例化等,生成对象只能调用无参的构造函数,而使用
// new关键字生成对象没有这个限制
ClassModelTest classModelTest = (ClassModelTest) Class.forName("com.midea.common.classTest.ClassModelTest")
.newInstance();
// getName():获得类的完整名字。
// getFields():获得类的public类型的属性。
// getDeclaredFields():获得类的所有属性。包括private 声明的和继承类
// getMethods():获得类的public类型的方法。
// getDeclaredMethods():获得类的所有方法。包括private 声明的和继承类
// getMethod(String name, Class[]
// parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes
// 参数指定方法的参数类型。
// getConstructors():获得类的public类型的构造方法。
// getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes
// 参数指定构造方法的参数类型。
// newInstance():通过类的不带参数的构造方法创建这个类的一个对象。
// https://www.jianshu.com/p/5b90a4e70783(如何实现一个简单的RPC)
// =============================反射
// RTTI,编译器在编译时打开和检查.class文件
// 反射,运行时打开和检查.class文件
System.out.println("ClassModelTest == " + classModelTest.toString());
// Class clazz = classModelTest.getClass();
Field[] fields = clazz.getDeclaredFields(); // 成员变量,获取类中所有的属性(public、protected、default、private),但不包括继承的属性,返回
// Field 对象的一个数组
// Class.getFields(): 获取类中public类型的属性,返回一个包含某些 Field 对象的数组,该数组包含此 Class
// 对象所表示的类或接口的所有可访问公共字段
// getDeclaredFields():
// 获取类中所有的属性(public、protected、default、private),但不包括继承的属性,返回 Field
// 对象的一个数组
// getField(String name): 获取类特定的方法,name参数指定了属性的名称
// getDeclaredField(String name): 获取类特定的方法,name参数指定了属性的名称
for (Field field : fields) {
System.out.println("field =========================== ");
System.out.println("field == " + field.toString());
System.out.println("getType == " + field.getType());// 返回这个变量的类型
System.out.println("getGenericType == " + field.getGenericType().getTypeName());// 如果当前属性有签名属性类型就返回,否则就返回
// Field.getType()
System.out.println("isEnumConstant == " + field.isEnumConstant());// 判断这个属性是否是枚举类
System.out.println("getName == " + field.getName());// 获取属性的名字
// -----------返回指定对象obj上此 Field 表示的字段的值,public的才可以用这个方法
// System.out.println("get == " + field.get(classModelTest));
//
// -----------将指定对象变量上此 Field 对象表示的字段设置为指定的新值,public的才可以用这个方法
// field.set(classModelTest, "fieldTest");
// System.out.println("classModelTest == " +
// classModelTest.toString());
// -----------该类为属性描述符类。使用PropertyDescriptor获取实体类中私有属性的值,并给私有属性赋值
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), clazz);
// 获得用于写入属性值的方法
Method method = propertyDescriptor.getWriteMethod();
// 运行这个方法写入属性值
method.invoke(classModelTest, "fieldWriteTest");
System.out.println("classModelTest == " + classModelTest.toString());
// 获得用于读取属性值的方法
Method methodRead = propertyDescriptor.getReadMethod();
Object readValue = methodRead.invoke(classModelTest);
System.out.println("readValue == " + readValue.toString());
// Introspector类: 可以将的类信息进行封装
// BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
// PropertyDescriptor[] proDescrtptors =
// beanInfo.getPropertyDescriptors();
}
// -----------
Method[] methods = clazz.getMethods();
for (Method method : methods) {
System.out.println("method =========================== ");
System.out.println("method == " + method.toString());
System.out.println("getName == " + method.getName());
Parameter[] parameters = method.getParameters();
for (Parameter parameter : parameters) {
System.out.println("parameter =========================== ");
System.out.println("getName == " + parameter.getName());
System.out.println("getName == " + parameter.getType());
}
System.out.println("getReturnType == " + method.getReturnType());
}
// -----------动态代理
// https://www.cnblogs.com/xiaoxiao7/p/6057724.html(AOP与JAVA动态代理)
// https://blog.csdn.net/lovejj1994/article/details/78080124(动态代理实现原理)
// 动态代理实现原理:就是按接口生成了一个新类,新类里的方法都经过改写调用InvocationHandler里的invoke
// 在运行期,目标类加载后,为接口动态生成代理类,将切面织入到代理类中
// 要代理的真实对象
Subject realSubject = new RealSubject();
InvocationHandler invocationHandler = new DynamicProxy(realSubject);
// 加载生成代理类
Subject subject = (Subject) Proxy.newProxyInstance(invocationHandler.getClass().getClassLoader(),
realSubject.getClass().getInterfaces(), invocationHandler);
// 调用代理的方法
subject.rent();// 实际都是调用invocationHandler里的invoke
subject.hello("world");
// -----------------
System.out.println("=============================");
DynamicProxy dynamicProxy = new DynamicProxy();
Subject sub = (Subject) dynamicProxy.bind(realSubject);
subject.rent();
subject.hello("world2");
// -----------CGLIB动态代理
// https://www.cnblogs.com/cruze/p/3865180.html(cglib 动态代理原理分析)
// 动态代理实现原理:通过生成子类,改写子类的方法中调用MethodInterceptor中的intercept来实现的,跟JDK动态代理类似
}
}