这篇博客将介绍Spring入门阶段对jdk动态代理的认识,实现如何创建一个jdk动态代理的程序。不适合处于JDK动态代理进阶段位的同学。本文阅读时长大约10分钟
【认识JDK动态代理】
在Java中有多种动态代理技术,最常见的是jdk动态代理和cglib动态代理,二者区别记住一点实现类有接口的Spring默认使用JDK动态代理,实现类没有接口的不能使用JDK动态代理而使用CGLIB动态代理
【学习建议】
对于处于入门阶段的同学来说,建议好好理解步骤3,步骤3实现的效果可以有多种方式,可能你在不同的博客里看到了其他方式,无关紧要,主要是把Proxy这个静态类里的newProxyInstance方法好好理解。然后把接口InvocationHandler中的invoke方法的每一行代码都好好去理解,暂时看不明白就多实践几遍,一切的学习都是从模仿开始。
【JDK动态代理实现步骤】
- 创建接口及实现类
- TestDao.java
package dynamic.jdk;
public interface TestDao {
public void save();
public void modyfi();
public void delete();
}
- TestDaoImpl.java
package dynamic.jdk;
public class TestDaoImpl implements TestDao {
@Override
public void save() {
System.out.println("保存");
}
@Override
public void modyfi() {
System.out.println("修改");
}
@Override
public void delete() {
System.out.println("删除");
}
}
- 创建切面类
- MyAspect.java
package aspect;
/*
* 切面类,可以定义多个通知,即增强处理的方法
*/
public class MyAspect {
public void check() {
System.out.println("模拟权限控制");
}
public void except() {
System.out.println("模拟异常处理");
}
public void log() {
System.out.println("模拟日志记录");
}
public void monitor() {
System.out.println("性能监测");
}
}
- 创建代理类(重要步骤!)
在JDK动态代理中代理类必须实现java.lang.reflect.InvocationHandler接口,并编写代理方法,在代理方法中需要通过Proxy实现动态代理
- JDKDynamicProcy.java
package dynamic.jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import aspect.MyAspect;
public class JDKDynamicProxy implements InvocationHandler {
//声明目标类接口对象(真实对象)
private TestDao testDao;
/*创建代理的方法,建立代理对象和真实对象的代理关系,并返回代理对象*/
public Object createProxy(TestDao testDao) {
this.testDao = testDao;
//1.类加载器
ClassLoader cld = JDKDynamicProxy.class.getClassLoader();
//2.被代理对象实现的所有接口
Class[] clazz = testDao.getClass().getInterfaces();
//3.使用代理类进行增强,返回代理后的对象
return Proxy.newProxyInstance(cld, clazz, this);
}
/*
* 代理的逻辑方法,所有的动态代理类的方法调用都交给该方法处理
* proxy是被代理对象
* method是将要被执行的方法
* args是执行方法时需要的参数
* return指放回代理结果
*/
@Override
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{
//创建一个切面
MyAspect myAspect = new MyAspect();
//前增强
myAspect.check();
myAspect.except();
//在目标类上调用方法并传入参数,相当于调用testDao中的方法
Object obj = method.invoke(testDao, args);
//后增强
myAspect.log();
myAspect.monitor();
return obj;
}
}
- 创建测试类
- JDKDynamicTest
package dynamic.jdk;
public class JDKDynamicTest {
public static void main(String[] args) {
//创建代理对象
JDKDynamicProxy jdkProxy = new JDKDynamicProxy();
//创建目标对象
TestDao testDao = new TestDaoImpl();
//从代理对象中获取增强后的目标对象,该对象是一个被代理的对象,他会进入代理的逻辑方法inxoke中
TestDao testDaoAdvice=(TestDao)jdkProxy.createProxy(testDao);
//执行方法
testDaoAdvice.save();
System.out.println("------------------");
testDaoAdvice.modyfi();
System.out.println("------------------");
testDaoAdvice.delete();
}
}