欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring Aop 源码解析

程序员文章站 2022-07-12 14:58:36
...
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. 时序图:
    Spring Aop 源码解析
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类,所以代理对象必须要有实现的接口;

相关标签: spring aop