Springboot源码 TargetSource解析
概述
在Spring框架中,AOP的核心就是AOP代理,而AOP代理的核心就是代理对象,而代理对象有可能是动态生成的,也有可能是预先存在的,在Spring框架中,预先存在的代理对象称为静态代理对象,动态生成的代理对象则使用CGLIB和JDK动态代理技术来实现,这里我们主要介绍CGLIB动态代理实现的过程。
Spring中使用CGLIB来对目标对象进行代理,生成的动态代理对象通常继承自目标对象的类型,同时又动态增加了一些方法用于实现增强逻辑。
TargetSource是Spring框架中一个非常重要的概念,用于描述代理对象和目标对象之间的关系。Spring中使用的代理分为两类,JDK动态代理和CGLIB动态代理,TargetSource就是用来描述这两种代理对象和原对象之间的关系,从而为代理对象提供目标对象的详细信息。
TargetSource
在Spring中,TargetSource是一个接口,声明了两个方法:
public interface TargetSource {
Class<?> getTargetClass();
Object getTarget() throws Exception;
void releaseTarget(Object target) throws Exception;
}
其中getTargetClass方法用于获取目标对象的Class类型,getTarget方法用于获取目标对象实例,releaseTarget方法则用于释放目标对象实例,在代理方法正常执行结束或意外异常结束时,都需要调用该方法释放目标对象,以便下次使用。
被代理对象的生成
下面我们通过一个Product类实现一个简易版的CGLIB动态代理示例,代码如下:
public class Product {
private String name;
public Product(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
在代理代码中,我们需要借助CGLIB库才能生成一个代理对象,因此需要在pom.xml文件中加入以下依赖:
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
代理类的生成过程如下:
public class ProductProxyFactory {
public static Product getProductProxy() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Product.class);
enhancer.setCallback(new ProductMethodInterceptor());
return (Product) enhancer.create();
}
}
在以上代码中,我们使用了Enhancer类对Product类进行了代理,同时为代理对象设置了回调,回调类为ProductMethodInterceptor。
方法拦截器
方法拦截器是代理对象和原对象之间桥梁,负责对代理对象的方法进行增强,CGLIB动态代理为每个代理类都提供了一个MethodInterceptor接口,用于实现方法拦截器的相关逻辑。以下是一个简单的示例:
public class ProductMethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("before " + method.getName() + " invoked");
Object result = methodProxy.invokeSuper(object, args);
System.out.println("after " + method.getName() + " invoked");
return result;
}
}
在以上代码中,我们对Product类的所有方法进行了拦截,并在拦截器中在方法前后加了一些日志输出,以便于观察代理对象和原对象之间的交互。
示例说明
示例1:获取目标对象类名
public class Main {
public static void main(String[] args) {
Product product = new Product("手机");
TargetSource targetSource = new SingletonTargetSource(product);
System.out.println(targetSource.getTargetClass().getName());
}
}
在以上示例中,我们创建了一个Product类的实例,然后将其包装成一个TargetSource对象,使用SingletonTargetSource实现,最后获取TargetSource的类名。
示例2:获取目标对象实例
public class Main {
public static void main(String[] args) {
Product product = new Product("手机");
TargetSource targetSource = new SingletonTargetSource(product);
try {
Object result = targetSource.getTarget();
System.out.println(((Product) result).getName());
targetSource.releaseTarget(result);
} catch (Exception e) {
e.printStackTrace();
}
}
}
在以上示例中,我们创建了一个Product类的实例,然后将其包装成一个TargetSource对象,使用SingletonTargetSource实现,最后获取TargetSource的实例对象,并调用Product类的getName方法输出结果,最后需要调用releaseTarget方法释放目标对象。
总结
TargetSource是Spring框架中描述动态代理与原对象之间关系的接口,它提供了获取目标对象类名和实例对象的方法,同时也提供了释放目标对象实例的方法,以便于下次使用。通过以上示例,我们可以了解到Spring如何使用CGLIB动态代理生成代理对象,同时也了解了TargetSource在代理对象和原对象之间的联系,为后续深入了解Spring的AOP技术打下基础。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Springboot源码 TargetSource解析 - Python技术站