spring源码(二)- 代理

ajc增强

通过插件,修改字节码文件

agent

通过插件,在类加载是修改

jdk代理:

普通类的过程:

先编写java 源代码 ,由源代码编译为字节码,最后经过类加载可以使用。

代理类:

没有源码,在运行期间直接生成代理类的字节码,生成的字节码需要类加载器加载才能使用

package com.tlj.app.parta;

import java.lang.reflect.Proxy;

/**
 * @Author: login
 * @Date: 2022/9/9
 * @Description:  只能针对接口进行代理
 */
public class JdkProxy {

	interface Foo {
		void   foo() ;
	}

	static class Target implements Foo {

		@Override
		public void foo() {
			System.out.println(" target");
		}
	}

	public static void main(String[] args) {
		//  用来加载运行期间动态生成的字节码文件
		ClassLoader classLoader = JdkProxy.class.getClassLoader();
		Target target = new Target();
		Foo foo = (Foo) Proxy.newProxyInstance(classLoader, new Class[] { Foo.class }, (proxy, method, args1) -> {
			System.out.println("before");
			// 代理返回目标方法执行的结果
			return method.invoke(target, args1);
		});

		foo.foo();
	}

}

jdk 代理是重新生成了接口的子类来实现代理,被代理类可以使final, jdk代理只能代理接口

Cglib动态代理

代理类是目标类的子类,不能对final类进行代理

package com.tlj.app.parta;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * @Author: login
 * @Date: 2022/9/9
 * @Description:
 */
public class CglibProxy {

	static class Target {
		public  void  foo() {
			System.out.println( "hhhhhhh");
		}
	}


	public static void main(String[] args) {

		Target target = new Target();
		Target proxyTarget = (Target) Enhancer
				.create(Target.class, (MethodInterceptor) (proxy, method, arg, methodProxy) -> {
					System.out.println("before");
					//  方式一   使用反射区调用
					Object result = method.invoke(target, arg);
					// 方式二   内部没有用反射,需要目标  spring用的就是这种机制
					methodProxy.invoke(target, arg);
					// 方式三  
					methodProxy.invokeSuper(proxy, arg);
					System.out.println("after");
					return result;
				});

		proxyTarget.foo();
	}
}

spring 选择代理的方式就是cglib

posted @ 2022-09-20 09:39  原来是晴天啊  阅读(42)  评论(0编辑  收藏  举报