java基础(动态代理)

一、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();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值