Spring Aop 源碼解析

1. 動態代理 Jdk 和Cglib

一、原理區別:

java動態代理是利用反射機制生成一個實現代理接口的匿名類,在調用具體方法前調用InvokeHandler來處理。

而cglib動態代理是利用asm開源包,對代理對象類的class文件加載進來,通過修改其字節碼生成子類來處理。

1、如果目標對象實現了接口,默認情況下會採用JDK的動態代理實現AOP
2、如果目標對象實現了接口,可以強制使用CGLIB實現AOP

3、如果目標對象沒有實現了接口,必須採用CGLIB庫,spring會自動在JDK動態代理和CGLIB之間轉換

package com.lvyuanj.core.service;

public interface UserService{
	void login(String username);
	void exit(String username);
}

package com.lvyuanj.core.service.Impl;

import com.lvyuanj.core.service.UserService;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService {

	@Override
	public void login(String username) {
		System.out.println(username+"進行登錄業務驗證");
	}

	@Override
	public void exit(String username) {
		System.out.println("exit---->"+username);
	}
}

package com.lvyuanj.core.service;

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

public class MyInvocationHandler implements InvocationHandler {

	private Object target;

	public MyInvocationHandler(Object target){
		super();
		this.target = target;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println("start------->");
		Object result = method.invoke(target, args);
		System.out.println("end---------<");
		return result;
	}

	public Object getProxy(){
		return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),target.getClass().getInterfaces(),this);
	}
}
package com.lvyuanj.core.service;

import com.lvyuanj.core.service.Impl.UserServiceImpl;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import sun.misc.ProxyGenerator;

import java.io.FileOutputStream;
import java.io.IOException;

@EnableAspectJAutoProxy
@ComponentScan
public class SpringAopDemo {

	public static void main(String[] args) throws IOException {

		UserService userService0 = new UserServiceImpl();
		MyInvocationHandler myInvocationHandler = new MyInvocationHandler(userService0);
		UserService myProxyUserService = (UserService) myInvocationHandler.getProxy();
		myProxyUserService.login("zhangsan");
	}
}

2. Spring Aop源碼解析
package com.lvyuanj.core.service;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class AuthAspect {

	@Around("execution(* com.lvyuanj.core.service.Impl.UserServiceImpl.*(..))")
	public void around(ProceedingJoinPoint joinPoint) throws Throwable {
		System.out.println("start ....");
		long l = System.currentTimeMillis();
		joinPoint.proceed();
		System.out.println("耗時:"+ (System.currentTimeMillis()-l));
	}
}
package com.lvyuanj.core.service;

import com.lvyuanj.core.service.Impl.UserServiceImpl;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import sun.misc.ProxyGenerator;

import java.io.FileOutputStream;
import java.io.IOException;

@EnableAspectJAutoProxy
@ComponentScan
public class SpringAopDemo {

	public static void main(String[] args) throws IOException {
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringAopDemo.class);

		UserService userService = applicationContext.getBean(UserService.class);
		String arvin = "arvin";
		userService.login(arvin);
	}
}

  1. 時序圖:
    在這裏插入圖片描述
new AnnotationConfigApplicationContext
	> org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
		>org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
		>org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)
		>org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization
			>org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization
			>org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary
			>org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy
				>org.springframework.aop.framework.ProxyFactory#getProxy(java.lang.ClassLoader)
					>org.springframework.aop.framework.ProxyCreatorSupport#createAopProxy
						>org.springframework.aop.framework.DefaultAopProxyFactory#createAopProxy   --- 判斷使用JdkDynamicAopProxy  和 ObjenesisCglibAopProxy 代理;是否實現了接口
							>org.springframework.aop.framework.JdkDynamicAopProxy#getProxy(java.lang.ClassLoader)   -- 獲取代理對象
								>java.lang.reflect.Proxy#newProxyInstance
								>java.lang.reflect.Proxy#getProxyClass0
								>java.lang.reflect.Proxy.ProxyClassFactory#apply  
								---->byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces, accessFlags); --- 代理類名稱獲取class字節,
								---->defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length);  -- 通過字節文件生成Class
package com.lvyuanj.core.service;

import com.lvyuanj.core.service.Impl.UserServiceImpl;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import sun.misc.ProxyGenerator;

import java.io.FileOutputStream;
import java.io.IOException;

@EnableAspectJAutoProxy
@ComponentScan
public class SpringAopDemo {

	public static void main(String[] args) throws IOException {
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringAopDemo.class);

		UserService userService = applicationContext.getBean(UserService.class);
		String arvin = "arvin";
		userService.login(arvin);
byte[] userServices = ProxyGenerator.generateProxyClass("UserServiceImpl", new Class[]{UserServiceImpl.class});

		FileOutputStream fileOutputStream = new FileOutputStream("D://UserServiceImpl.class");

		fileOutputStream.write(userServices);

		fileOutputStream.close();
	}
}

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

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

public final class UserServiceImpl extends Proxy implements com.lvyuanj.core.service.Impl.UserServiceImpl {
    private static Method m1;
    private static Method m3;
    private static Method m8;
    private static Method m2;
    private static Method m6;
    private static Method m5;
    private static Method m7;
    private static Method m9;
    private static Method m0;
    private static Method m4;

    public UserServiceImpl(InvocationHandler var1) throws  {
        super(var1);
    }

    public final boolean equals(Object var1) throws  {
        try {
            return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final void login(String var1) throws  {
        try {
            super.h.invoke(this, m3, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final void notify() throws  {
        try {
            super.h.invoke(this, m8, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final void wait(long var1) throws InterruptedException {
        try {
            super.h.invoke(this, m6, new Object[]{var1});
        } catch (RuntimeException | InterruptedException | Error var4) {
            throw var4;
        } catch (Throwable var5) {
            throw new UndeclaredThrowableException(var5);
        }
    }

    public final void wait(long var1, int var3) throws InterruptedException {
        try {
            super.h.invoke(this, m5, new Object[]{var1, var3});
        } catch (RuntimeException | InterruptedException | Error var5) {
            throw var5;
        } catch (Throwable var6) {
            throw new UndeclaredThrowableException(var6);
        }
    }

    public final Class getClass() throws  {
        try {
            return (Class)super.h.invoke(this, m7, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final void notifyAll() throws  {
        try {
            super.h.invoke(this, m9, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final int hashCode() throws  {
        try {
            return (Integer)super.h.invoke(this, m0, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final void wait() throws InterruptedException {
        try {
            super.h.invoke(this, m4, (Object[])null);
        } catch (RuntimeException | InterruptedException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m3 = Class.forName("com.lvyuanj.core.service.Impl.UserServiceImpl").getMethod("login", Class.forName("java.lang.String"));
            m8 = Class.forName("com.lvyuanj.core.service.Impl.UserServiceImpl").getMethod("notify");
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m6 = Class.forName("com.lvyuanj.core.service.Impl.UserServiceImpl").getMethod("wait", Long.TYPE);
            m5 = Class.forName("com.lvyuanj.core.service.Impl.UserServiceImpl").getMethod("wait", Long.TYPE, Integer.TYPE);
            m7 = Class.forName("com.lvyuanj.core.service.Impl.UserServiceImpl").getMethod("getClass");
            m9 = Class.forName("com.lvyuanj.core.service.Impl.UserServiceImpl").getMethod("notifyAll");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
            m4 = Class.forName("com.lvyuanj.core.service.Impl.UserServiceImpl").getMethod("wait");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

接着把得到的 $Proxy0 實例強制轉換成UserServiceImpl,並將引用賦給subject。當執行userService.login()方法時,就調用了$Proxy0類中的login()方法,進而調用父類Proxy中的h的invoke()方法.即InvocationHandler.invoke()

1.爲什麼我們java動態代理被代理對象必須是接口了?
答: 由於java是單繼承多實現,通過上面反編譯獲取UserServiceImpl 代理類源碼可用出來,UserServiceImpl 默認就已經繼承了Proxy類,所以代理對象必須要有實現的接口;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章