携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第7天,点击查看活动详情
哈喽,大家好!我是Why,一名在读学生,目前刚刚开始进入自己的编程学习生涯。虽然学习起步较晚,但我坚信做了才有0或1的可能。学了一段时间以后也是选择在掘金上分享自己的日常笔记,也希望能够在众多道友的大家庭中打成一片。 本文主要讲解动态代理之基于Jdk的动态代理,如果大家读后觉得有用的话,还请大家多多支持博主:欢迎 ❤️点赞👍、收藏⭐、留言💬 ✨✨✨个人主页:JinHuan
动态代理
基于Jdk的动态代理
/*
newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
ClassLoader :类加载器,因为动态代理类,借助别人的类加载器。一般使用被代理对象的类加载器。
Class<?>[] interfaces:接口类对象的集合,针对接口的代理,针对哪个接口做代理,一般使用的就是被代理对象的接口。
InvocationHandler:句柄,回调函数,编写代理的规则代码
public Object invoke(Object arg0, Method arg1, Object[] arg2)
Object arg0:代理对象
Method arg1:被代理的方法
Object[] arg2:被代理方法被执行的时候的参数的数组
*/
基础版
package com.jinhuan.dynamicProxy;
import com.jinhuan.service.BookService;
import com.jinhuan.service.IService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @Author jinhuan
* @Date 2022/7/4 8:12
* Description:基于JDK的动态代理
*/
public class JdkProxy {
public static void main(String[] args) {
//被代理对象
BookService bookService = new BookService();
//返回代理对象
/**
* 第一个参数:被代理对象的类加载器
* 第二个参数:被代理对象的接口对象集合
* 第三个参数:回调函数,在这里编写代理的规则
* */
IService service = (IService) Proxy.newProxyInstance(
bookService.getClass().getClassLoader(),
bookService.getClass().getInterfaces(),
new InvocationHandler() {
/**
* 第一个参数:被代理对象
* 第二个参数:被代理对象的方法
* 第三个参数:被代理对象的参数
* */
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
System.out.println("开始事务!");
/**
* method.invoke:加强方法
* 第一个参数:被代理对象
* 第二个参数:需要加强的方法参数
* */
Object invoke = method.invoke(bookService, args);//这个相当于核心方法
System.out.println("结束事务");
return invoke;
} catch(Exception e) {
System.out.println("事务回滚");
e.printStackTrace();
throw e;
}finally {
System.out.println("finally-----");
}
}
}
);
//使用代理对象【干活】
service.add();
}
}
优化版
第一次优化
优化ProxyHandler
第二次优化
优化出代理工厂
JdkProxy
package com.jinhuan.dynamicProxy;
import com.jinhuan.service.BookService;
import com.jinhuan.service.IService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @Author jinhuan
* @Date 2022/7/4 8:12
* Description:基于JDK的动态代理
*/
public class JdkProxy {
public static void main(String[] args) {
//被代理对象
BookService bookService = new BookService();
//返回代理对象
/**
* 第一个参数:被代理对象的类加载器
* 第二个参数:被代理对象的接口对象集合
* 第三个参数:回调函数,在这里编写代理的规则
* */
IService service = (IService) Proxy.newProxyInstance(
bookService.getClass().getClassLoader(),
bookService.getClass().getInterfaces(),
new InvocationHandler() {
/**
* 第一个参数:被代理对象
* 第二个参数:被代理对象的方法
* 第三个参数:被代理对象的参数
* */
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
System.out.println("开始事务!");
/**
* method.invoke:加强方法
* 第一个参数:被代理对象
* 第二个参数:需要加强的方法参数
* */
Object invoke = method.invoke(bookService, args);//这个相当于核心方法
System.out.println("结束事务");
return invoke;
} catch(Exception e) {
System.out.println("事务回滚");
e.printStackTrace();
throw e;
}finally {
System.out.println("finally-----");
}
}
}
);
//使用代理对象【干活】
service.add();
}
}
MyProxyHandler
package com.jinhuan.dynamicProxy;
import com.jinhuan.aop.Aop;
import com.jinhuan.service.IService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* @Author jinhuan
* @Date 2022/7/4 8:45
* Description:
*/
public class MyProxyHandler implements InvocationHandler {
private IService service;
private Aop aop;
public MyProxyHandler(IService service, Aop aop) {
this.service = service;
this.aop = aop;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
aop.before();
Object invoke = method.invoke(service, args);//这个相当于核心方法
aop.after();
return invoke;
} catch(Exception e) {
aop.exception();
e.printStackTrace();
throw e;
}finally {
aop.myFinally();
}
}
}
ProxyFactory
package com.jinhuan.dynamicProxy;
import com.jinhuan.aop.Aop;
import com.jinhuan.aop.LogAop;
import com.jinhuan.aop.TranAop;
import com.jinhuan.service.BookService;
import com.jinhuan.service.IService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @Author jinhuan
* @Date 2022/7/4 8:56
* Description:专门产生代理类的工厂
*/
public class ProxyFactory {
private IService service;
private Aop aop;
public ProxyFactory(IService service, Aop aop) {
this.service = service;
this.aop = aop;
}
/**
* @param :
* @return java.lang.Object
* decription: 获取动态代理的实例
*/
public Object getProxyInstance(){
return Proxy.newProxyInstance(
service.getClass().getClassLoader(),
service.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
aop.before();
Object invoke = method.invoke(service, args);//这个相当于核心方法
aop.after();
return invoke;
} catch(Exception e) {
aop.exception();
e.printStackTrace();
throw e;
}finally {
aop.myFinally();
}
}
}
);
}
}
TestJdkProxy
package com.jinhuan.test;
import com.jinhuan.aop.Aop;
import com.jinhuan.aop.LogAop;
import com.jinhuan.aop.TranAop;
import com.jinhuan.dynamicProxy.MyProxyHandler;
import com.jinhuan.dynamicProxy.ProxyFactory;
import com.jinhuan.service.BookService;
import com.jinhuan.service.IService;
import org.junit.Test;
import java.lang.reflect.Proxy;
/**
* @Author jinhuan
* @Date 2022/7/4 8:36
* Description:
*/
public class TestJdkProxy {
@Test
/**
* 第一次优化Jdk动态代理
* */
public void test() {
//被代理对象
BookService bookService = new BookService();
Aop tranAop = new TranAop();
Aop logAop = new LogAop();
//返回代理对象
/**
* 第一个参数:被代理对象的类加载器
* 第二个参数:被代理对象的接口对象集合
* 第三个参数:回调函数,在这里编写代理的规则
* */
IService service = (IService) Proxy.newProxyInstance(
bookService.getClass().getClassLoader(),
bookService.getClass().getInterfaces(),
new MyProxyHandler(bookService,tranAop)
);
//使用代理对象【干活】
service.add();
}
/**
* 第二次优化
* */
@Test
public void test01(){
//被代理对象
BookService bookService = new BookService();
Aop tranAop = new TranAop();
Aop logAop = new LogAop();
//获取被代理对象 一级代理
IService service1 = (IService) new ProxyFactory(bookService, tranAop).getProxyInstance();
//二级代理
IService service2 = (IService) new ProxyFactory(service1, logAop).getProxyInstance();
service1.add();
service2.add();
}
}