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 - 返回调用该方法的代理实例
查了很多资料这一篇解开谜底了
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());
}
}
}