一直想分享一些技术,为多变的技术带来一些分享,之后会慢慢的带来一些本身学过的技术,和本身的一些心得,最近想分享effect java,设计模式,并发编程,一些java集合源码和并发包源码,jvm,mybatis源码,nio,nio2,netty,grpc,和一些数据结构算法,mysql,githtml
今天就先来分析静态代理和动态代理java
假设有个这样的场景,想对一个Source类进行增强,好比在不改变Source类的基础,执行Source类的method()方法执行先后打印一些日记,实现步骤mysql
public interface Sourceable {
void method();
}复制代码
public class Source implements Sourceable {
@Override
public void method() {
System.out.println("the original method");
}
}复制代码
public class Proxy implements Sourceable {
private Sourceable source;
public Proxy(Source source) {
this.source = source;
}
@Override
public void method() {
before();
source.method();
after();
}
private void before() {
System.out.println("method() run begin");
}
private void after() {
System.out.println("method() run end");
}
}复制代码
public class ProxyTest {
public static void main(String[] args) {
Source source = new Source();
Proxy proxy = new Proxy(source);
proxy.method();
}
}复制代码
method() run begin
the original method
method() run end
复制代码
咱们常常在使用mybatis的时候mapper只是个接口,调用接口方法就能执行以下git
IUserMapper userMapper = session.getMapper(IUserMapper.class);//获取接口,已是代理接口
userMapper.getById(1);//调用mybatis内部的MapperProxy类的invoke
复制代码
咱们先来看下核心的Proxy.newProxyInstance(arg1,arg2,arg3)方法算法
(ServiceInterface) Proxy.newProxyInstance(ServiceInterface.class.getClassLoader(), serviceInterface.getClass().getInterfaces(), InvocationHandler);复制代码
第一个参数arg1是接口的classloader,就是为了加载动态生成的代理类,arg2是接口,为了生成的代理类实现此接口,拥有实现此接口的方法,最后一个参数arg3,InvocationHandler,目的是生成的代理类对象,执行方法时,调用此内部的invoke()方法sql
接下来咱们开始实现它,有两种状况,一种是接口有实现类,咱们在内部直接用反射进行调用实现类方法,第二种就是mybatis实现方式,只有接口没有实现类,咱们先实现由实现类的方式编程
public interface ServiceInterface {
void println();
}复制代码
public class ServiceInterfaceImpl implements ServiceInterface {
@Override
public void println() {
System.out.println("ServiceInterfaceImpl");
}
}复制代码
public class MyInvocationHandler implements java.lang.reflect.InvocationHandler {
private Object target;
public MyInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("2222");
method.invoke(target, args);
System.out.println("3333");
return null;
}
}复制代码
public class ProxyTest {
public static void main(String[] args) {
ServiceInterface serviceInterface = new ServiceInterfaceImpl();
InvocationHandler InvocationHandler = new MyInvocationHandler(serviceInterface);
ServiceInterface proxy = (ServiceInterface) Proxy.newProxyInstance(ServiceInterface.class.getClassLoader(), serviceInterface.getClass().getInterfaces(), InvocationHandler);
proxy.println();
}
}复制代码
咱们再来看下第二种方式只有接口没有实现类设计模式
public interface ServiceInterface {
void println();
}复制代码
public class MyInvocationHandler implements java.lang.reflect.InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("2222");
System.out.println("3333");
return null;
}
}复制代码
public class ProxyTest {
public static void main(String[] args) {
InvocationHandler InvocationHandler = new MyInvocationHandler();
ServiceInterface proxy = (ServiceInterface) Proxy.newProxyInstance(ServiceInterface.class.getClassLoader(), new Class[]{ServiceInterface.class}, InvocationHandler);
proxy.println();
}
}复制代码
流程是调用Proxy.newProxyInstance()方法会动态生成实现传入的第二个参数的接口,而后第三个参数是handler,调用proxy.println(),其实动态类println()方法实际上是调handler的invoke方法,咱们接下来看下反编译后的动态类bash
// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3) fieldsfirst
package com.sun.proxy;
import java.lang.reflect.*;
import proxyStudy.ServiceInterface;
public final class $Proxy0 extends Proxy
implements ServiceInterface
{
private static Method m3;
private static Method m1;
private static Method m0;
private static Method m2;
public $Proxy0(InvocationHandler invocationhandler)
{
super(invocationhandler);
}
public final void println()
{
try
{
super.h.invoke(this, m3, null);
return;
}
catch(Error _ex) { }
catch(Throwable throwable)
{
throw new UndeclaredThrowableException(throwable);
}
}
public final boolean equals(Object obj)
{
try
{
return ((Boolean)super.h.invoke(this, m1, new Object[] {
obj
})).booleanValue();
}
catch(Error _ex) { }
catch(Throwable throwable)
{
throw new UndeclaredThrowableException(throwable);
}
}
public final int hashCode()
{
try
{
return ((Integer)super.h.invoke(this, m0, null)).intValue();
}
catch(Error _ex) { }
catch(Throwable throwable)
{
throw new UndeclaredThrowableException(throwable);
}
}
public final String toString()
{
try
{
return (String)super.h.invoke(this, m2, null);
}
catch(Error _ex) { }
catch(Throwable throwable)
{
throw new UndeclaredThrowableException(throwable);
}
}
static
{
try
{
m3 = Class.forName("proxyStudy.ServiceInterface").getMethod("println", new Class[0]);
m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] {
Class.forName("java.lang.Object")
});
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
}
catch(NoSuchMethodException nosuchmethodexception)
{
throw new NoSuchMethodError(nosuchmethodexception.getMessage());
}
catch(ClassNotFoundException classnotfoundexception)
{
throw new NoClassDefFoundError(classnotfoundexception.getMessage());
}
}
}
复制代码