愚迷:住法 着相 念境
文章目录
前言
maven中需要mybatis的知识
shit!
一、代理模式
1.1 概念
目标对象不可访问,通过代理对象增强功能访问
生活中:
房东(目标对象)
房屋中介(代理对象)
你,我(客户端对象)
厂商(目标对象)
门店(代理对象)
你,我(客户端对象)
1.2 作用
- 控制目标对象的访问
- 增强功能
1.3 分类
1.3.1静态代理
它是代理模式的一种,具备以下特点:
- 目标对象和代理对象实现同一个业务接口
- 目标对象必须实现接口
- 代理对象在程序运行前就已经存在
- 能够灵活的进行目标对象的切换,却无法进行功能的灵活处理(使用动态代理解决此问题)
1.3.2动态代理(分为JDK动态代理和CGLib动态代理)
代理对象在程序运行的过程中动态在内存构建,可以灵活的进行业务功能的切换
二、面向接口编程
类中的成员变量设计为接口,方法的形参设计为接口,方法的返回值设计为接口,调用时接口指向实现类
三、动态代理
3.1jdk动态代理
- 目标对象必须实现业务接口
- JDK代理对象不需要实现业务接口
- JDK动态代理的对象在程序运行时动态的在内存中构建
- JDK动态代理灵活的进行业务功能的切换
- 本类中的方法(非接口中的方法)不能被代理
3.2jdk动态代理用到的类和接口
它是使用现在的工具类完成JDK动态实现
-
Proxy类
java.long.reflect.Proxy包下的类,有一个方法 Proxy.newProxyInstance(…);专门用来生成动态代理对象
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,//类加载器
Class<?>[] interfaces, //目标对象实现的所有接口
InvocationHandler h //它就类似于Agent的功能,代理的功能和目标对象的业务功能调用在这
)
throws IllegalArgumentException
{…} -
Method类
反射用的类,用来进行目标对象的方法的反射调用
method对象接住我们正在调用的方法sing(),show()
method就等同于sing(),show()
method.invoke() ==》 手工调用目标方法 -
InvocationHandler接口
它是实现代理和业务功能的,我们在调用时,使用匿名内部类实现
动态代理实例(增加功能更灵活,只需在接口和实现类中增加功能,代理中不用管):
public class ProxyFactory {
//类中的成员变量设计为接口,目标对象
Service target;
//传入目标对象
public ProxyFactory(Service target){
this.target=target;
}
//返回动态代理对象
public Object getAgent(){
return Proxy.newProxyInstance(
//ClassLoader loader, 类加载器,完成目标对象的加载
target.getClass().getClassLoader(),
//Class<?>[] interfaces, 目标对象实现的所有接口
target.getClass().getInterfaces(),
//InvocationHandler h 实现代理功能的接口,我们传入的匿名内部实现
new InvocationHandler() {
@Override
public Object invoke(
//创建代理对象
Object proxy,
//method就是目标方法sing()或者show()
Method method,
//目标方法的参数
Object[] args) throws Throwable {
//代理功能
System.out.println("预定时间....");
//代理功能
System.out.println("预定场地....");
//主业务功能实现
//target.sing(); 还是写死了方法的调用,不成
Object obj = method.invoke(target, args);
//代理功能
System.out.println("预定结算费用....");
return obj;//切记:这个是目标方法的返回值
}
}
);
}
}
只有实现类中实现的接口中的方法可以被动态代理,在实现类中本地书写的方法不能被动态代理
3.3CGLib动态代理
又称为子类代理,通过动态的在内存中构建子类对象,重写父类的方法,进行代理功能的增强
如果目标对象没有实现接口,则只能通过CGLib子类代理来进行功能增强
子类代理是通过字节码框架ASM来实现的
CGLib实现的步骤
- 需要spring-core-5.2.5 依赖
- 引入功能包后,就可以在内存中动态构建子类
- 被代理的类不能为final,否则报错(final即不可变(重写),自然不能被代理)
- 目标对象的方法如果为final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法(静态没有多态)
总结
看javase
反射
注解