新人书写,仅做记录,谢谢观看
若有不当之处,还望指正
8、spring动态代理
8.1 动态字节码技术
8.1.1 静态字节码技术
-
编写.java文件,后编译成class文件
-
实例化对象时,通过ClassLoader对象将class文件读取到JVM中,
-
最后在JVM中再次通过ClassLoader对象生成该对象的Class对象,最终通过Class对象实例化成对象
8.1.2 动态字节码技术
-
运行时,通过动态字节码框架(如Cglib,ASM,javassist)或JDKProxy提供的类方法(Proxy.newProxyInstance),在JVM中生成字节码文件
-
再在JVM中通过ClassLoader对象生成该对象的Class对象,最终通过Class对象实例化为对象
对比:动态字节码技术不需要人为编写.class文件,只要配置得当,交由JDK自动生成即可
注:生成的动态字节码将随着JVM的关闭而消失
8.2 静态代理
即自己手工书写代理类,将目标类方法、额外功能写入代理类方法中,
书写的代理类需要编译成.class文件,即静态的字节码文件,JVM通过读取静态的字节码文件生成对象,完成功能
8.3 动态代理
目标类通过代理设计模式生成代理类,代理类的字节码文件则通过动态字节码技术生成在JVM中,最后通过ClassLoader对象生成实例化代理对象,即动态代理=代理设计模式+动态字节码技术
JVM运行结束,则动态字节码消失,即生成代理类消失,下次使用,则再次创建
8.3.1 专用名词
概念名称 | 意义 |
---|---|
Target(目标类) | 指被代理的接口或子类对象,如service实现类 |
Proxy(代理类) | 代理类=同一接口+目标类+增强方法 |
JoinPoint(连接点) | 指目标类中所有的方法 |
PointCut(切入点) | 指目标类中添加了增强方法的方法, 注:连接点不一定会增强,但切入点一定是增强了的 |
8.3.2 技术分类
Spring动态代理对象的生成主要有JDKProxy技术和Cglib技术,其中,当目标类是接口时,则使用JDKProxy技术,若为接口实现类或子类时,使用Cglib技术
8.3.3 JDKProxy技术
即使用JDK的Proxy.newProxyInstance()方法,生成并实例化代理对象
- 方法详解:interfaces指定目标类及其实现的接口,h指定增强方法,这两个参数已经将代理对象的字节码文件写入JVM中,但由于需要ClassLoader对象的支持,JVM中的字节码文件才可以生成对象,故loader指定ClassLoader对象(每个.class文件都会有一个ClassLoader对象,且通用,故可任意借用)
Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
参数:
loader:类加载器,通过该类加载器将动态代码生成实例化对象,可任意借用,可通过Obj.getClass().getClassLoader()方法获取
interfaces:目标类或接口的接口字节码文件数组,可通过Obj.getClass().getInterfaces()方法获取
h:编写增强方法需要实现的接口
返回值:代理对象实例化后的对象
- 接口详解
InvocationHandler接口,用于指定增强方法,需要实现内置的invoke()方法
public Object invoke(Object proxy, Method method, Object[] args)
参数:
proxy:生成的代理类对象
method:目标类中的所有方法对应的方法对象,即连接点
args[]:连接点的参数
返回值:即连接点执行后的返回值
8.3.4 CGlib技术
使用时,需要导入cglib包
8.4 spring动态代理相关接口
8.4.1 MethodBeforeAdvise
- 接口方法:实现该方法,可对目标类中的方法进行前置方法增强(注:需要配置到spring的aop配置中,使用aop:advisor标签对实现类bean与切入点表达式进行组合)
public void before(Method method, Object[] args, Object target)
参数:
method:目标类中的方法
args:目标类中的方法参数
target:目标类
8.4.2 MethodInterceptor
接口方法:实现该方法,可对目标类中的方法进行环绕增强(注:需要配置到spring的aop配置中,使用aop:advisor标签对实现类bean与切入点表达式进行组合)
public Object invoke(MethodInvocation invocation)
参数:
invocation:方法对象,可通过该对象对方法进行回调
返回值:
返回原方法的返回值,可自定义
public class MyMethodInterceptor_around implements MethodInterceptor{
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("MethodInterceptor:前置通知");
Object res = null;
try {
res = invocation.proceed();
} catch (Exception e) {
System.out.println("MethodInterceptor:异常通知");
} finally {
System.out.println("MethodInterceptor:最终通知");
}
System.out.println("MethodInterceptor:后置通知");
return res;
}
}