最近在复习SSM框架,Spring底层使用的就是动态代理的原理
下面开始复习jdk动态代理:
jdk动态代理: 基于接口的动态代理,必须要有接口
下面假想一种关系:
首先创建产品工厂类:
public class ProductFactory {
/**
* 制造产品
*/
public void make(){
System.out.println("生成了一个产品");
}
}
以前旧的直销方式:
public class OldSale {
public void sale(Float money){
System.out.println("正在以"+money+"价格卖出");
}
}
现在新的方式:
先定义总经销商接口:
public interface NewSale {
/**
* 卖产品
* @param money
*/
public void sale(Float money);
}
然后是接口的实现,销售网点:
/**
* 经销商创建的销售网点
*/
public class NewSaleImpl implements NewSale {
@Override
public void sale(Float money) {
System.out.println("正在以"+money+"价格卖出");
}
}
创建代理对象来监管销售网点是否挣钱(这就是新的增强功能):
public class TestProxy {
@Test
public void testJDKProxy(){
//真实的对象
NewSale newSale = new NewSaleImpl();
//创建代理对象-- **本质上就是接口的一个实现类**
//参数1: 类加载器
//参数2:类实现的接口
//参数3:真实对象的增强部分:实现了InvocationHandler接口的实现类
//匿名内部类也是该接口的实现类
NewSale sale = (NewSale) Proxy.newProxyInstance(newSale.getClass().getClassLoader(), newSale.getClass().getInterfaces(),
new InvocationHandler() {
/**
* 增强内容
* @param proxy : 代理对象
* @param method : 代理的方法,未增强的方法
* @param args : 代理的方法的参数
* @return 代理的方法的返回值
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//生成产品
ProductFactory productFactory = new ProductFactory();
productFactory.make();
//开始销售:通过反射执行真实对象的方法
//参数1:真实的对象
//参数2:方法的参数
method.invoke(newSale,args );
//判断是否挣钱了
//卖的价格:args[0] 假设产品的成本是 1500
if( (Float)args[0] > 1500){
//卖的价格高于成本,挣了,可卖
System.out.println("卖的价格高于成本,挣了,可卖");
}else{
//卖的价格低于成本,赔了,不可卖
System.out.println("卖的价格低于成本,赔了,不可卖");
}
return null;
}
});
sale.sale(1000F);
}
}
下面对源码进行分析:
InvocationHandler是一个接口,它只有一个方法:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
在定义增强逻辑类时,需要实现该接口,并在invoke方法里实现增强逻辑和对真实对象方法的调用。
代理对象的产生是通过调用Proxy类的静态方法,newProxyInstance方法的源码:
传进三个参数:类加载器,接口,调用处理器
类加载器ClassLoader:确保返回的代理对象和真实对象由同一个类加载器加载
接口 interfaces:用于定义代理类应该实现的方法
调用处理器InvocationHandler:用于定义代理类的增强逻辑
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h) {
Objects.requireNonNull(h);//判断一下h是否为null
final Class<?> caller = System.getSecurityManager() == null
? null
: Reflection.getCallerClass();//进行安全检查,如果非null,则反射得到方法调用者的类
/*
* Look up or generate the designated proxy class and its constructor.//查询(在缓存中已经有)或生成指定的代理类的class对象和他的构造方法
*/
Constructor<?> cons = getProxyConstructor(caller, loader, interfaces);
return newProxyInstance(caller, cons, h);
}
invoke方法的源码
@CallerSensitive
@ForceInline // to ensure Reflection.getCallerClass optimization
@HotSpotIntrinsicCandidate
public Object invoke(Object obj, Object... args)
throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException
{
if (!override) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz,
Modifier.isStatic(modifiers) ? null : obj.getClass(),
modifiers);
}
MethodAccessor ma = methodAccessor; // read volatile
if (ma == null) {
ma = acquireMethodAccessor();
}
return ma.invoke(obj, args);
}
运行结果:
——————————————————————————————————————————
下面开始复习cglib动态代理:
cglib是基于类的动态代理
需要引入第三方jar包
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
注意:
代理对象其实就是原来类的一个子类
所以代理的类不能用final修饰
其他部分的代码都与上面相同,下面是测试程序:
/**
* cglib动态代理
* 代理对象是真实对象的一个子类
*/
@Test
public void testCglibProxy(){
//真实对象
OldSale oldSale = new OldSale();
//创建cglib代理对象
//1. 创建增强类对象
Enhancer enhancer = new Enhancer();
//2. 指定代理对象的父类
enhancer.setSuperclass(oldSale.getClass());
//3. 指定增强的内容
//MethodInterceptor :接口是方法拦截器
enhancer.setCallback(new MethodInterceptor() {
/***
* 增强的内容
* @param o 代理对象,增强后的对象
* @param method 代理的方法
* @param objects 代理的方法的参数
* @param methodProxy 代理方法,增强后的方法
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
//生成产品
ProductFactory factory = new ProductFactory();
factory.make();
//开始销售,执行真实对象的内容
method.invoke(oldSale, objects);
//判断是否挣钱了
//卖的价格:objects[0] 假设产品的成本是 1500
if( (Float)objects[0] > 1500){
//卖的价格高于成本,挣了,可卖
System.out.println("卖的价格高于成本,挣了,可卖");
}else{
//卖的价格低于成本,赔了,不可卖
System.out.println("卖的价格低于成本,赔了,不可卖");
}
return null;
}
});
//4. 创建代理对象:
OldSale saleProxy = (OldSale)enhancer.create();
saleProxy.sale(2000f);
}
代理对象执行sale方法,实际实行的是intercept方法。