MyBatis反射和动态代理的定义
这篇文章主要介绍"MyBatis反射和动态代理的定义",在日常操作中,相信很多人在MyBatis反射和动态代理的定义问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"MyBatis反射和动态代理的定义"的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
理解反射和动态代理
反射
首先看看官网对反射的定义:
可以通过java代码,获取当前加载类的字段、方法、构造函数等信息,并在安全限制内,使用反射字段、方法、构造函数进行操作。
简单来说,可以在运行时获得程序中每一个类型的成员信息。程序中定义的对象,其类型都是在编译期确定的,而反射可以动态地创建对象,并访问或调用其成员。
动态代理
所谓代理,是一个人或组织代替另一个人或组织做事,主要有3个角色:访问者、代理人、被代理人,访问者经由代理人,与被代理人交互,中间会加入一些自己的处理。
所谓的动态代理,是说在编译时不需要定义代理类,而是在运行时创建,这个是关键:在运行时创建代理类。
Class对象
Class类是一个实实在在的类,存在于java.lang包中,用来表示运行时类型信息。Class对象表示自定义类的类型信息,比如创建一个User类,JVM就会创建一个User对应的Class对象,保存User类相关的类型信息,该对象保存在jvm堆中,作为访问方法区中User类型信息的接口。
在使用自定义类时,会首先检查这个类的Class对象是否已经加载,如果没有加载,默认的类加载器就会先根据类名查找.class文件,Class对象就会被加载到内存。
可以通过下面3种方法获取Class对象:
使用Class类的forName静态方法;
直接获取某一个对象的class;
调用某个对象的getClass()方法;
Class对象是反射的基础,提供了获取类信息的方法,后面会介绍。
反射提供的功能
java反射框架主要提供以下内容:
在运行时判断对象所属的类;
在运行时创建对象;
在运行时获取类包含的成员变量、方法、父类、接口等信息;
在运行时调用一个对象的方法;
下面举例说明相关功能
创建实例:
//获取String所对应的Class对象Class> c = User.class;//获取String类带一个String参数的构造器Constructor constructor = c.getConstructor(String.class);//根据构造器创建实例User user = (User)constructor.newInstance("calm");
获取方法:
//返回类或接口声明的所有方法,包括私有的,但不包括继承的方法public Method[] getDeclaredMethods() throws SecurityException//所有public方法,包括继承的方法public Method[] getMethods() throws SecurityException//返回一个特定的方法,第一个参数为方法名称,后面的参数为方法参数对应Class的对象public Method getMethod(String name, Class>... parameterTypes)
调用方法:
Class> userClass=User.class;Object obj = userClass.newInstance();Method method =klass.getMethod("addRole",String.class);method.invoke(obj,"超级管理员");
JDK动态代理
JDK本身提供了动态代理的实现,要求被代理者必须实现接口。
public static Object newProxyInstance(ClassLoader loader,Class>[] interfaces,InvocationHandler h)
第一个参数为类加载器,第二个参数是被代理者实现的接口列表,第三个参数是实现了InvocationHandler接口的对象。
InvocationHandler是一个接口,用于规范执行被代理者的方法,可在执行方法前后,添加公共的处理代码。生成的动态代理类包含一个InvocationHandler属性,调用对应方法时,会触发invoke方法的调用。
public class JDKProxy implements InvocationHandler { private Object targetObject;//被代理对象 public Object newProxy(Object targetObject) { this.targetObject = targetObject; return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),targetObject.getClass().getInterfaces(), this);} public Object invoke(Object proxy, Method method, Object[] args)//invoke方法 throws Throwable { Object ret = null; ret = method.invoke(targetObject, args); return ret; } }
测试代码:
JDKProxy jdkProxy=new JDKProxy();UserService userService = (UserService) jdkProxy.newProxy(new UserServiceImp()); userService.addRole("超级管理员");
JDK动态代理的基本原理是根据定义好的规则,用传入的接口创建一个新类。
CGLIB动态代理
JDK动态代理要求必须有接口,CGLIB(Code Generate Library)动态代理没有这个要求,它是通过创建一个被代理类的子类,然后使用ASM字节码库修改代码来实现的。
public class CGLibProxy implements MethodInterceptor { private Object targetObject; //被代理对象 public Object createProxyObject(Object obj) { this.targetObject = obj; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(obj.getClass()); enhancer.setCallback(this); Object proxyObj = enhancer.create(); return proxyObj; } public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { Object obj = null; obj = method.invoke(targetObject, args); return obj; } }
测试代码:
CGLibProxy cgLibProxy=new CGLibProxy();UserService userService = (UserService) cgLibProxy.newProxy(new UserServiceImp()); userService.addRole("超级管理员");
到此,关于"MyBatis反射和动态代理的定义"的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!