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动态代理类似
}
}
分享到:
相关推荐
如果目标类是final的,或者包含final方法,CGLIB则无法生成子类,这时它会退化到使用基于方法的代理,即通过动态生成实现所有接口的代理类来实现。 2. **CGLIB使用**: - 首先,你需要在项目中引入CGLIB的jar包。...
CGLib,全称为Code Generation Library,是一个强大的高性能的代码生成库,它在运行期扩展Java类与实现Java接口。在Java编程中,我们有时需要在运行时动态地创建或修改类,CGLib就是为此目的而设计的。它广泛应用于...
2. CGLib代理项目: - src/main/java:包含目标类 - target/classes:编译后的class文件,包括目标类的class文件,以及由CGLib生成的子类class文件 - 测试代码:展示如何使用Enhancer创建代理对象并调用方法 这...
CGlib的工作原理是基于Java的反射API和ASM库,它可以生成新的子类来实现动态代理。当一个类没有实现接口时,CGlib会创建该类的子类并在子类中添加方法拦截器。这种方法比使用Java的标准动态代理(java.lang.reflect....
##### 3.1 动态代理原理 - **接口**:目标对象必须实现接口,因为Java动态代理是基于接口的。 - **代理类**:由JVM在运行时自动生成。 - **InvocationHandler**:实现了`InvocationHandler`接口的类,负责处理代理...
总的来说,CGLIB_2.2.2与ASM_3.3.1的结合使用,为Java开发者提供了一种高效且灵活的动态代理实现方式,极大地扩展了Java代码的能力。在实际开发中,尤其是在需要进行面向切面编程或需要高性能代理的情况下,CGLIB是...
- 相比Java动态代理,CGLIB更适合处理没有接口的类,而JDK动态代理则需要目标对象实现至少一个接口。 - 与AspectJ相比,CGLIB的AOP实现较为简单,但AspectJ提供了更全面的切面定义和编译时织入,而CGLIB则主要在...
2. **配置**:在Spring框架中,如果需要使用CGLIB进行AOP代理,需要在配置文件中启用CGLIB代理,例如在XML配置中添加 `<aop:aspectj-autoproxy/>` 或者在Java配置中使用 `@EnableAspectJAutoProxy(proxyTargetClass ...
2. **性能**:在处理大量代理对象时,CGLib通常比Java动态代理更快,因为它使用的是字节码技术,而Java动态代理需要反射。 3. **灵活性**:CGLib可以修改类的行为,甚至包括私有方法,而Java动态代理只能处理接口...
【动态代理原理】 动态代理是Java中用于在运行时创建代理对象的一种机制,它允许我们在程序执行过程中动态地创建代理类并实现特定接口,从而在调用目标方法之前或之后添加额外的功能。动态代理通常用于实现如AOP...
CGlib动态代理的原理是,它利用Java的反射API和ASM库(一个轻量级的字节码操作和分析框架),在运行时动态地生成一个子类,这个子类继承自目标类,并且覆盖了所有非final的方法。当调用这些方法时,CGlib会通过`...
CGLib的工作原理是:当程序调用一个被CGLib代理的方法时,CGLIB会生成一个新的子类,并在这个子类中覆盖原方法。这个新的子类会在运行时被加载,然后通过子类的方法来调用原方法,这样就可以在方法调用前后插入...
五、CGlib与Java反射动态代理的对比 虽然Java自带的反射API提供了简单的动态代理实现,但仅限于实现了接口的类。对于没有接口的类,CGlib提供了一种更灵活的解决方案。然而,CGlib的性能通常稍逊于Java反射API,...
CGLIB通过生成子类并在子类中拦截方法调用来实现代理,这与Java的反射API不同,反射API是通过在运行时动态修改类的实例来实现代理的。 **CGLIB工作原理:** 1. **子类生成**:CGLIB通过ASM库在运行时动态生成目标类...
在Java中,当你需要在运行时动态扩展一个类或者创建一个类的代理时,CGLIB就是一个非常有用的工具。它通过ASM库来操作字节码,创建新类或接口的实例。在SSH(Struts + Spring + Hibernate)集成框架中,CGLIB被用作...
动态代理分为两类:基于接口的代理(Java动态代理)和基于具体类的代理(CGLIB)。本文主要介绍基于接口的Java动态代理。 #### 二、Java动态代理机制 Java动态代理主要依赖于`java.lang.reflect.Proxy`类和`java....
CGlib是Java开发中的一个非常重要的库,它是一个强大的、高性能的代码生成库,主要用于扩展Java类和实现动态代理。这篇原创文章“CGlib源代码分析”旨在深入探讨CGlib的工作原理和内部机制,帮助开发者更好地理解和...
### CGLIB动态代理原理 CGLIB通过字节码技术生成代理类。当目标类没有实现接口时,CGLIB会生成一个目标类的子类,并在子类中对方法进行拦截,这样就能在不修改原有代码的情况下,插入额外的功能。CGLIB使用ASM库(在...
2. **动态代理**:CGLib可以用来创建动态代理,当需要在运行时为某个类增加额外行为时,可以利用它生成该类的子类并覆盖特定方法。 3. **性能优化**:在某些情况下,CGLib可以用于代码优化,例如,通过动态生成的...