只能针对接口进行代理
public class JDKProxy {
public static void main(String[] args) {
//目标对象
Targer targer = new Targer();
//当前类的类加载器
ClassLoader loader = JDKProxy.class.getClassLoader();
//Proxy.newProxyInstance : 创建一个新的代理实例,运行期间生成代理类的字节码
/*
参数说明:
loader 加载代理类在运行期间动态生成的字节码
new Class[]可以代理多个Foo接口
对行为进行封装
*/
Foo proxy = (Foo)Proxy.newProxyInstance(loader, new Class[]{Foo.class}, new InvocationHandler() {
//参数说明:代理对象自己、正在执行的方法对象、方法传来的实际参数
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before...");
//目标 方法(参数)
//方法反射调用目标对象
//目标对象 和 参数
Object result = method.invoke(targer, args);
//让代理也返回目标方法执行的结果
System.out.println("after...");
return result;
}
});
//调用代理的父方法
proxy.foo();
}
interface Foo{
void foo();
}
static class Targer implements Foo{
@Override
public void foo() {
System.out.println("target foo");
}
}
}
原理:
以下是一个半成品的proxy,可以看到实现的方式很巧妙
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @author 我见青山多妩媚
* @date 2023/4/15 0015 16:06
* @Description TODO
*/
public class Proxy$0 {
interface Foo{
int foo();
void bar();
}
static class Target implements Foo {
@Override
public int foo() {
System.out.println("target foo");
return 1;
}
@Override
public void bar() {
System.out.println("bar foo");
}
}
public static void main(String[] args) {
Foo proxy = new $Proxy0(new InvocationHandler() {
@Override
public Object invoke(Object proxy,Method method,Object[] args) throws InvocationTargetException, IllegalAccessException {
//1.实现功能增强
System.out.println("before...");
//2.调用目标
// new Target().foo();
//反射调用
return method.invoke(new Target(),args);
}
});
proxy.foo();
proxy.bar();
}
//抽象成一个代理接口,所有代理的方法就不用写在代理内内部,具体实现具体做,不会写死,成为动态代理
interface InvocationHandler{
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable;
}
}
import com.example.springreaddemo.SpringRead.Demo02_SpringAop.proxy.JDK.Proxy$0.Foo;
import com.example.springreaddemo.SpringRead.Demo02_SpringAop.proxy.JDK.Proxy$0.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.UndeclaredThrowableException;
/**
* @author 我见青山多妩媚
* @date 2023/4/15 0015 15:59
* @Description TODO
*/
//JDK 代理类
public class $Proxy0 implements Foo {
private InvocationHandler invocationHandler;
public $Proxy0(InvocationHandler invocationHandler){
this.invocationHandler = invocationHandler;
}
@Override
public int foo() {
try {
//将foo的方法 以及 方法参数传过去,调用foo方法
Object invoke = invocationHandler.invoke(this,foo, new Object[0]);
return (int)invoke;
} catch (RuntimeException | Error e) { //运行时异常直接抛出
throw e;
} catch (Throwable e){
throw new UndeclaredThrowableException(e); //检查异常转化为运行异常抛出
}
}
@Override
public void bar() {
try {
//将foo的方法 以及 方法参数传过去,调用bar方法
invocationHandler.invoke(this,bar,new Object[0]);
} catch (Throwable e) {
e.printStackTrace();
}
}
static Method foo;
static Method bar;
static {
try {
foo = Foo.class.getMethod("foo");
bar = Foo.class.getMethod("bar");
} catch (NoSuchMethodException e) {
throw new NoSuchMethodError(e.getMessage()); //比较严重的问题
}
}
}
JDK生成的代理类,不会有源码阶段,直接到字节码,这个动态生成代理类并且直接到字节码的方式叫ASM
与JDK不同,可以针对很对进行代理
public class CglibProxy {
static class Target{
public void foo(){
System.out.println("target foo...");
}
}
public static void main(String[] args) {
Target target = new Target();
Target proxy = (Target)Enhancer.create(Target.class, new MethodInterceptor() {
@Override
/*
参数:
1.o 代理类自己
2.method 代理类内执行的方法
3.objects 参数
4.方法对象,和method参数有些区别
*/
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("before...");
// method.invoke(target,objects); //方法反射调用目标
//methodProxy 可以避免反射调用 内部没有用反射
// Object result = methodProxy.invoke(target, objects); //需要目标才能调用自己 spring使用的是这个
Object result = methodProxy.invokeSuper(o, objects); //内部没有用反射,需要代理
System.out.println("after...");
return result;
}
});
proxy.foo();
}
}
代理类是目标类的子类,所以目标类不能被final修饰,
因为是代理,相当于是对目标类的方法重写,所以方法也不能被final修饰
内部实现:
我们知道cglib是根据继承实现的,我们这有个父类
public class Target {
public void save(){
System.out.println("save");
}
public void save(int i){
System.out.println(i+"save");
}
public void save(long i){
System.out.println("save long");
}
}
public class Proxy extends Target {
private MethodInterceptor methodInterceptor;
public void setMethodInterceptor(MethodInterceptor methodInterceptor){
this.methodInterceptor = methodInterceptor;
}
static Method save0;
static Method save1;
static Method save2;
static MethodProxy save0Proxy;
static MethodProxy save1Proxy;
static MethodProxy save2Proxy;
static {
try {
save0 = Target.class.getMethod("save");
save1 = Target.class.getMethod("save", int.class);
save2 = Target.class.getMethod("save", long.class);
//参数:
//目标对象
//代理对象
//方法参数描述符
//带增强功能的方法
//带原始功能的方法
save0Proxy = MethodProxy.create(Target.class,Proxy.class,"()V","save","saveSuper");
//参数类型为整型
save1Proxy = MethodProxy.create(Target.class,Proxy.class,"(I)V","save","saveSuper");
//长整型为大写J
save2Proxy = MethodProxy.create(Target.class,Proxy.class,"(J)V","save","saveSuper");
} catch (NoSuchMethodException e) {
throw new NoSuchMethodError(e.getMessage());
}
}
//代理原始功能的方法
public void saveSuper(){
super.save();
}
public void saveSuper(int i){
super.save(i);
}
public void saveSuper(long i){
super.save(i);
}
//属于待增强功能的方法
@Override
public void save() {
try {
methodInterceptor.intercept(this,save0,new Object[0],save0Proxy);
} catch (Throwable e) {
throw new UndeclaredThrowableException(e);
}
}
@Override
public void save(int i) {
try {
methodInterceptor.intercept(this,save1,new Object[]{i},save1Proxy);
} catch (Throwable e) {
throw new UndeclaredThrowableException(e);
}
}
@Override
public void save(long i) {
try {
methodInterceptor.intercept(this,save2,new Object[]{i},save2Proxy);
} catch (Throwable e) {
throw new UndeclaredThrowableException(e);
}
}
}
public class Main {
public static void main(String[] args) {
Proxy proxy = new Proxy();
Target target = new Target();
proxy.setMethodInterceptor(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects,
MethodProxy methodProxy) throws Throwable {
System.out.println("before...");
//内部有反射
// return method.invoke(target,objects);
//内部无反射调用 结合目标使用
// return methodProxy.invoke(target,objects);
//内部无反射
return methodProxy.invokeSuper(o,objects);
}
});
proxy.save();
proxy.save(1);
proxy.save(2L);
}
}
内部实现,和jdk的区别,他可以做到不使用反射进行动态的代理
不使用反射调用的原理:
package com.example.springreaddemo.SpringRead.Demo02_SpringAop.proxy.Cglib;
import org.springframework.cglib.core.Signature;
/**
* @author 我见青山多妩媚
* @date 2023/4/16 0016 20:21
* @Description TODO
*/
//desc 不用反射实现代理的原理
public class TargetFastClass {
//将目标对象的方法对应为三个签名
static Signature s0 = new Signature("save","()V");
static Signature s1 = new Signature("save","(I)V");
static Signature s2 = new Signature("save","(J)V");
/**
* 根据方法的前面信息,获取目标方法的编号
*
* save 0
* save(int i) 1
* save(long i) 2
* @param signature 签名 包括方法的名字、参数、返回值等等
* @return 编号
*/
public int getIndex(Signature signature){
if(s0.equals(signature)){
return 0;
}else if (s1.equals(signature)){
return 1;
}else if(s2.equals(signature)){
return 2;
}else {
return -1;
}
}
/**
* 根据获取到的方法编号,调用目标对象中的方法
* @param index 编号
* @param target 目标对象
* @param args 参数列表
* @return 返回目标对象
*/
public Object invoke(int index,Object target,Object[] args){
if(index == 0){
((Target) target).save();
return null;
}else if(index == 1){
((Target) target).save((int) args[0]);
return null;
}else if(index == 2){
((Target) target).save((long) args[0]);
return null;
}else{
throw new RuntimeException("无此方法");
}
}
}
MethodProxy内部不使用反射的原理:
public class ProxyFastClass {
//将目标对象的方法对应为三个签名
static Signature s0 = new Signature("saveSuper","()V");
static Signature s1 = new Signature("saveSuper","(I)V");
static Signature s2 = new Signature("saveSuper","(J)V");
/**
* 根据方法的前面信息,获取目标方法的编号
*
* save 0
* save(int i) 1
* save(long i) 2
* @param signature 签名 包括方法的名字、参数、返回值等等
* @return 编号
*/
public int getIndex(Signature signature){
if(s0.equals(signature)){
return 0;
}else if (s1.equals(signature)){
return 1;
}else if(s2.equals(signature)){
return 2;
}else {
return -1;
}
}
/**
* 根据获取到的方法编号,调用目标对象中的方法
* @param index 编号
* @param proxy 代理对象
* @param args 参数列表
* @return 返回目标对象
*/
public Object invoke(int index,Object proxy,Object[] args){
if(index == 0){
((Proxy) proxy).saveSuper();
return null;
}else if(index == 1){
((Proxy) proxy).saveSuper((int) args[0]);
return null;
}else if(index == 2){
((Proxy) proxy).saveSuper((long) args[0]);
return null;
}else{
throw new RuntimeException("无此方法");
}
}
public static void main(String[] args) {
ProxyFastClass proxyFastClass = new ProxyFastClass();
int index = proxyFastClass.getIndex(new Signature("saveSuper", "()V"));
System.out.println(index);
proxyFastClass.invoke(index,new Proxy(),new Object[0]);
}
}
实际上就是调用了代理类
jdk在调用第17次时一个方法生成一个代理类,而cglib会给生成一个代理类,对应两个fastClass,一个对应目标代理,一个对代理类代理,生成的代理类数目比jdk少