SpringAOP之原理实现

48 阅读2分钟

Aop 实现方式

 

原理:

 

通过JDK Proxy代理InvocationHandler 这个类调用处理 两者结合实现动态代理

  • 先看jdk的描述

此方法是代理实例的,调用处理程序必须实现接口 (一般我们都是面向接口 开发,spring默认采用这种方法实现)

  • 方法

 

再看看构造 方法的详细描述

调用invoke方法

需要传递三个参数,proxy对象也就是jdk的动态代理对象,第一个 是返回的代理对象,第二个是方法(调用的方法实例),第三个是个参数。

 

以下为代码实现

package com.udeam.aspect;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import com.udeam.Service.UseSercvice;
import com.udeam.Service.UseSercviceImpl;

//aop原理
public class AopPrinciple  implements InvocationHandler{

	
	public static void main(String[] args) {
		//jdk Proxy 动态代理 + 调用处理类
		
		
		
		
		//传入的代理对象
		UseSercvice userSercvice = new  UseSercviceImpl();
		
		//调用处理类
		InvocationHandler  invocationHandlerClass =  new AopPrinciple(userSercvice);
		
		//代理对象   
		UseSercvice  proxy =  (UseSercvice) Proxy.newProxyInstance(
				userSercvice.getClass().getClassLoader(), 
				userSercvice.getClass().getInterfaces(), invocationHandlerClass);
		
		proxy.say("hello");
		
	}
	
	
	
	//需要传入的代理对象
	private Object object;
	
	public AopPrinciple() {}
	 
	public AopPrinciple(Object object) {
		 this.object=object;
	}
	
	 


	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		
		
		System.out.println("方法名: " + method.getName());
		
		
		Object invoke = method.invoke(object, args);
		
		return invoke;
	}
	
	
}

 

service 实现类

public class UseSercviceImpl  implements UseSercvice{


	public String say(String name) {
		System.out.println(name);
		return name;
	}

}

 

 

问题:

 

这里要写成这样子     Object invoke = method.invoke(object, args);

而不是下面:

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
       
        System.out.println("方法名: "   + method.getName());
        Object invoke = method.invoke(proxy , args);
        return invoke;
    }

不然会报错:

 

疑问 proxy 这个参数有什么用?

API中   proxy - 返回调用该方法的代理实例

 

查了很多资料这一篇解开谜底了

stackoverflow.com/questions/2…

proxy 是被返回的代理对象  $Proxy0 可以用此代理 对象继续进行代理!

 

修改代码:

修改service 

public interface UseSercvice {

	
	public void say();
	public UseSercvice say(String name);
}

 

返回次代理对象


	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println("方法名 : " + method.getName());
		Object invoke = method.invoke(object, args);
		System.out.println("输出次代理对象的class: "+ proxy.getClass().getName());
		 //proxy 是被返回的代理对象
		return proxy;
	}
	
	

然后代理并且打印出内存地址:

	UseSercvice say = proxy.say("hello").say("hahha ...");
		System.out.println("内存地址:"+say.getClass().toString());

 

内存地址是   com.sun.proxy.$Proxy0 $Proxy0 这个类 是干什么 的?

JDK 代理类 Proxy 实际 上动态生成  $Proxy0类代理的

打开自己项目路径com.sun..proxy路径 下面 , 可以看待 字节码

 

反编译:

package com.sun.proxy;

import com.udeam.Service.UseSercvice;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class $Proxy0
  extends Proxy
  implements UseSercvice
{
  private static Method m1;
  private static Method m2;
  private static Method m4;
  private static Method m3;
  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 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 UseSercvice say(String paramString)
    throws 
  {
    try
    {
      return (UseSercvice)this.h.invoke(this, m4, new Object[] { paramString });
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }
  
  public final void say()
    throws 
  {
    try
    {
      this.h.invoke(this, m3, null);
      return;
    }
    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") });
      m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
      m4 = Class.forName("com.udeam.Service.UseSercvice").getMethod("say", new Class[] { Class.forName("java.lang.String") });
      m3 = Class.forName("com.udeam.Service.UseSercvice").getMethod("say", 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());
    }
  }
}