代理模式
Jdk动态代理
通过反射机制,创建一个代理类对象实例并返回。用户进行方法调用时使用创建代理对象时,需要传递该业务类的类加载器(用来获取业务实现类的元数据,在包装方法是调用真正的业务方法)、接口、handler实现类,被代理的对象必须实现了某一个接口。
public <T> T getProxy(T target) {
return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), new MyInvocationHandler(
target));
}
CGLIB动态代理
一个java字节码的生成工具,它动态生成一个被代理类的子类,子类重写被代理的类的所有不是final的方法。在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑,通过增强器Enhancer和拦截器MethodInterceptor去实现。
创建代理的步骤:
生成代理类的二进制字节码文件;
加载二进制字节码,生成Class对象;
通过反射机制获得实例构造,并创建代理类对象
public static <T> T getObjectProxy(T target, Callback[] callbacks,
CallbackFilter filter) {
// 1、创建加强器用来创建动态代理
Enhancer enhancer = new Enhancer();
// 2 、为加强器指定要代理的业务类(即:为下面生成的代理类指定父类)
enhancer.setSuperclass(target.getClass());
// 3、 设置回调:对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实现intercept()方法进行拦
// 3.1callback用于类的所有方法进行加强后返回
// enhancer.setCallback(callback);
// 3.2callbacks对指定的方法进行拦截,需要配置拦截链CallbackFilter
enhancer.setCallbacks(callbacks);
enhancer.setCallbackFilter(filter);
// 4、创建动态代理类对象并返回
return (T) enhancer.create();
}
Spring创建动态代理
AbstractAutoProxyCreator根据配置获取到所有可以引用bean的增强器List以后,就需要为bean创建代理,Spring代理又分为JDK动态代理和CGLIB动态代理两种方式,所以按照常规方式,需要一个ProxyFactory去根据需求创建具体的Proxy对象,Spring也是这么去做的。
protected Object createProxy(
Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
//1、获取当前类钟的属性
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
//2、添加代理接口
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true)