最近在研究mybaits的源码,mapper是接口,就是用的动态代理返回的代理对象;
必须记录一下,今天终于整明白动态代理了,也希望看到这篇文章的小伙伴们能够明白
接口是不能实例化的
如果我们要实例化的话 必须实现该接口,有个实现类才得行!!
1.使用匿名类的方式
public class TestProxy1 {
interface UserMapper{
void getUser();
}
public static void main(String[] args) {
UserMapper userMapper = new UserMapper() {
public void getUser() {
System.out.println("使用匿名类的方法");
}
};
}
}
2.使用动态代理的方式
//2.动态代理:第一个参数:类加载器 第二个参数:需要代理的接口 第三个参数:InvocationHandler的实现类
UserMapper o = (UserMapper)Proxy.newProxyInstance(TestProxy1.class.getClassLoader(), new Class<?>[]{UserMapper.class}, new InvocationHandler() {
//Method: 调用的方法 args:方法里面的参数值
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(method+"----"+args[0]);
return null;
}
});
//通过代理对象调用方法
o.getUser(12);
输出结果:
可以看到,我们代理成功了!!!!
分析动态代理
不知道大家能否明白
下面是我的拙见,有什么不对的欢迎指出
jdk帮我们底层帮我们动态的创建了一个实现类/代理类嘛:
Class<?> cl = getProxyClass0(loader, intfs);
通过构造方法创建对象,传入handler
cons.newInstance(new Object[]{h});
动态生成的代理类实现了接口,这也就是为啥我们可以通过代理对象调用相关的方法,下面可以查看生成的代理类信息
实现类里面可以通过反射获取到方法Method,
在实现方法的时候其实调用的是InvocationHandler的invoke方法,
然后传入Method,args,在我们的invokeHandler里面就是让我们用户去实现的具体要执行的操作
看一下为我们生成的代理类
帮我们创建了一个代理类
public final class $Proxy0 extends Proxy
implements TestProxy1.UserMapper
{
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m0;
public $Proxy0(InvocationHandler paramInvocationHandler)
throws
{
super(paramInvocationHandler);
}
public final boolean equals(Object paramObject)
throws
{
try
{
return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final void getUser(Integer paramInteger)
throws
{
try
{
this.h.invoke(this, m3, new Object[] { paramInteger });
return;
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final String toString()
throws
{
try
{
return (String)this.h.invoke(this, m2, null);
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final int hashCode()
throws
{
try
{
return ((Integer)this.h.invoke(this, m0, null)).intValue();
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
static
{
try
{
m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
m3 = Class.forName("proxy.TestProxy1$UserMapper").getMethod("getUser", new Class[] { Class.forName("java.lang.Integer") });
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
return;
}
catch (NoSuchMethodException localNoSuchMethodException)
{
throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
}
catch (ClassNotFoundException localClassNotFoundException)
{
throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
}
}
}
我简单整理一下哈:
谢谢!!!
下面我贴上代码奥,有不正确的欢迎指出,大家一起进步!!
我下面的代码是动态代理的代码,跟上面的其实差不多奥!!
package proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//接口
interface User{
void say();
}
class LayzUser implements User{
public void say() {
System.out.println("懒惰的用户在说话了");
}
private void truduce() {
System.out.println("介绍自己的方法");
}
}
//我们的handler,具体的操作行为,用户去实现
class UserInvoke implements InvocationHandler {
//这个才是真实的对象
private Object o;
public UserInvoke(Object o1){
this.o = o1;
}
//proxy:代理类 method方法 args:参数
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("----日志--------");
Object invoke = method.invoke(o, args);//注意这里是o对象,调用对象的方法 ,方法前后进行日志打印
System.out.println("----日志--------");
return invoke;
}
}
public class ProxyDemo1 {
public static void main(String[] args) {
//动态代理 要在对象的方法前后打印日志
LayzUser layzUser = new LayzUser();
//动态的生成代理类 为啥这个代理类可以调用相同的方法
// 为了保持行为的一致性,代理类和委托类会实现相同的接口,所以在访问者看来两者没有丝毫的区别
User o =(User) Proxy.newProxyInstance(ProxyDemo1.class.getClassLoader(), new Class<?>[]{User.class}, new UserInvoke(layzUser));
o.say();
}
}