Spring核心IOC与AOP
Spring是一个非常优秀的开源框架,它的诞生解决企业级开发的复杂,框架的主要优势就是其分层架构,方便集成各种优秀的框架,在学习Spring的时候,接触到IOC与AOP这两个概念,下面一起来学习。
1、IOC
IOC全称Inversion of Control
,中文翻译为控制反转
,在Spring中所谓的IOC就是一个管理对象生命周期及对象依赖关系的容器,也称为IOC容器。
IOC容器分为两类:低级容器(BeanFactory),高级容器(ApplicationContext);
1.1 BeanFactory
BeanFactory是最顶层的一个接口,定义了IOC容器的基本功能,可以理解为一个HashMap,Key是Bean名称,Value是Bean的实例。
public interface BeanFactory {
/**
* 对FactoryBean的转义定义,因为如果要使用Bean的名称获取FactoryBean对象,
* 需要在Bean名称前加上&符号,获取Bean本身对象则不用加
*/
String FACTORY_BEAN_PREFIX = "&";
/**
* 根据Bean的名字,获取IOC容器中的Bean实例
*/
Object getBean(String name) throws BeansException;
/**
* 根据Bean名字和Class类型获取Bean实例,增加类型的安全验证机制
*/
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
/**
* 根据Bean名字获取Bean实例,
* 在创建Bean实例时允许指定构造函数参数/工厂方法参数覆盖Bean中定义的默认参数
* (仅在创建新实例而不是检索现有实例时应用)
*/
Object getBean(String name, Object... args) throws BeansException;
/**
* 根据类型获取IOC容器中的Bean实例
*/
<T> T getBean(Class<T> requiredType) throws BeansException;
/**
* 根据类型获取IOC容器中的Bean实例,
* 在创建Bean实例时允许指定构造函数参数/工厂方法参数覆盖Bean中定义的默认参数
* (仅在创建新实例而不是检索现有实例时应用)
*/
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
/**
* 根据Bean名字判断IOC容器中是否包含该Bean的实例
*/
boolean containsBean(String name);
/**
* 根据Bean名字判断该Bean是不是单例
*/
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
/**
* 根据Bean名字判断该Bean是不是原型(多例)
*/
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
/**
* 根据Bean名字判断是否与指定类型匹配
* 更具体地说,通过Bean名字调用getBean()返回对象是否可分配给指定目标类型的对象。
* 将别名转换回对应的规范bean名称。
*/
boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
/**
* 根据Bean名字判断是否与指定类型匹配
* 更具体地说,通过Bean名字调用getBean()返回对象是否可分配给指定目标类型的对象。
* 将别名转换回对应的规范bean名称。
*/
boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
/**
* 根据Bean名字获取Bean的class类型
*/
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
/**
* 跟据Bean名字获取Bean的别名,如果是使用别名,那么原名也会检索出来
*/
String[] getAliases(String name);
}
1.2 ApplicationContext
ApplicationContext是BeanFactory的子接口,在BeanFactory的基础上增加更多的功能,例如支持信息源,实现国际化,访问资源,支持应用事件。
ApplicationContext接口对容器的实现是在AbstractApplicationContext抽象类开始的,该抽象类中实现了refresh(),无论使用ClassPathXmlApplicationContext还是使用AnnotationConfigApplicationContext来实例化IOC容器,都会调用AbstractApplicationContext抽象类的refresh()方法,那就看一下该方法。
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing. --> 准备刷新此上下文。
// 刷新前的预处理。
prepareRefresh();
// Tell the subclass to refresh the internal bean factory. --> 告诉子类刷新内部bean工厂。
// 获取新的BeanFactory。
// 获取的BeanFactory来自子类GenericApplicationContext默认初始化创建(this.beanFactory = new DefaultListableBeanFactory();)Bean工厂。
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context. --> 准备bean工厂以供在此上下文中使用。
// BeanFactory的预准备工作(BeanFactory进行一些设置)。
// 1、设置BeanFactory的类加载器、支持表达式解析器...
// 2、添加部分BeanPostProcessor【ApplicationContextAwareProcessor】
// 3、设置忽略的自动装配的接口EnvironmentAware、EmbeddedValueResolverAware、xxx;
// 4、注册可以解析的自动装配;我们能直接在任何组件中自动注入:BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext
// 5、添加BeanPostProcessor【ApplicationListenerDetector】
// 6、添加编译时的AspectJ;
// 7、给BeanFactory中注册一些能用的组件;environment【ConfigurableEnvironment】、systemProperties【Map<String, Object>】、systemEnvironment【Map<String, Object>】
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses. --> 允许在上下文子类中对bean工厂进行后处理。
// BeanFactory准备工作完成后进行的后置处理工作;
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context. --> 调用上下文中注册为bean的工厂处理器。
// 执行BeanFactoryPostProcessor的方法;
// 1、先执行BeanDefinitionRegistryPostProcessor
// 2、先执行再执行BeanFactoryPostProcessor的方法
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation. --> 注册拦截bean创建的bean处理器。
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context. --> 初始化此上下文的消息源。
// 初始化MessageSource组件(做国际化功能;消息绑定,消息解析);
initMessageSource();
// Initialize event multicaster for this context. --> 为此上下文初始化事件派发器。
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses. --> 初始化特定上下文子类中的其他特殊bean。
onRefresh();
// Check for listener beans and register them. --> 检查侦听器bean并注册它们。
// 将项目里所有的ApplicationListener注册到容器中。
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons. --> 实例化所有剩余的(非延迟初始化)单例。
// getBean()-->doGetBean()
// 先获取缓存中保存的单实例Bean。如果能获取到说明这个Bean之前被创建过(所有创建过的单实例Bean都会被缓存起来)(从DefaultSingletonBeanRegistry的 final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256)中获取的);缓存中获取不到,开始Bean的创建对象流程;
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event. --> 最后一步:发布对应的事件。
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
总结:
- 1、SpringIOC容器在启动的时候,会先保存所有注册进来的Bean的定义信息;
- xml注册bean;
- 注解注册bean;@service,@Controller,@Component,@Bean …
- 2、Spring容器会在合适的时候创建这些Bean;
- 用到这个Bean时候,利用getBean()创建Bean并保存在容器中;
- 统一创建剩下的Bean,通过finishBeanFactoryInitialization()方法创建;
- 3、每一个Bean创建完都会使用各种后置处理器来对Bean进行增强;
- AutowiredAnnotationBeanPostProcessor:处理自动注入功能;
- AnnotationAwareAspectJAutoProxyCreator:处理AOP功能;
- 4、最后一步发布相应的事件;
2、AOP
全称Aspect Oriented Programing
,中文翻译为面向切面编程
,将涉及多业务流程的通用功能抽取并单独封装,形成独立的切面,在不改变原有的逻辑的基础上通过预编译和运行期动态代理实现在合适的时机将这些切面横向切入到业务流程指定的位置中,便于程序功能的统一维护。
2.1AOP相关名词:
- Aspect:切面,且日业务流程的一个独立模块;
- Join point:连接点,业务流程在运行过程中需要插入切面的具体位置;
- Advice:通知,是切面的具体实现方法,可分为前置通知、后置通知、异常通知、最终通知、环绕通知;
- Pointcut:切入点,用于定义通知应该切入到哪些连接点,不用的通知可能切入到不同的连接点上;
- Target:目标对象,被一个或者多个切面所通知的对象;
- Proxy:代理对象,将通知应用到目标对象之后被动态创建的对象;
- Weaving:切入,也称为织入,将切面应用到目标对象从而创建一个新的代理对象的过程;
2.2 AOP代理类型
Java中动态代理方式有JDK 动态代理
和 CGLIB 代理
,Spring中AOP代理就是使用这两种代理来实现的,默认如果目标对象是接口,则使用JDK动态代理,否则使用CGLB来生成代理类。
-
JDK动态代理
使用JDK动态代理需要实现两个接口,一是目标类实现接口,二是实现扩展处理器InvocationHandler接口。
使用JDK动态代理的步骤:
- 1、通过实现InvocationHandler接口来自定义自己的InvocationHandler;
- 2、通过Proxy.getProxyClass获得动态代理类,再通过反射机制获取代理类的构造方法,然后通过构造函数获取代理对象并将自定义的InvocationHandler实例作为参数传入,返回的是代理对象;还有一种更加简单的方式,是通过Proxy.newProxyInstance(加载接口的类加载器,目标类的接口,自定义的InvocationHandler实例)方法,直接返回生成的代理对象;
- 3、通过代理对象调用目标方法;
// 1、创建目标类的接口 public interface DemoService { String demo(); } // 2、实现目标类接口 public class DemoServiceImpl implements DemoService { @Override public String demo() { System.out.println("---------------DemoServiceImpl demo"); return "DemoServiceImpl demo"; } } // 3、实现扩展处理器InvocationHandler接口的invoke方法 public class MyInvocationHandler implements InvocationHandler { private Object target; public MyInvocationHandler(Object target){ this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("MyInvocationHandler --- Before invoke " + method.getName()); Object invoke = method.invoke(target, args); System.out.println("MyInvocationHandler --- After invoke " + method.getName()); return invoke; } } /** * 4、测试 * Proxy的newProxyInstance方法生成返回代理对象,通过返回的代理类对象调用目标方法。 */ public class ProxyDemo { public static void main(String[] args) { DemoServiceImpl demoService = new DemoServiceImpl(); MyInvocationHandler invocationHandler = new MyInvocationHandler(demoService); DemoService instance = (DemoService)Proxy.newProxyInstance(demoService.getClass().getClassLoader(), demoService.getClass().getInterfaces(), invocationHandler); instance.demo(); } }
JDK代理生成的class内容如下;生成的$Proxy0类,实现了DemoService接口,由此可知
JDK代理生成的类是目标类的兄弟类
。public final class $Proxy0 extends Proxy implements DemoService { private static Method m1; private static Method m3; private static Method m2; private static Method m0; public $Proxy0(InvocationHandler var1) throws { super(var1); } public final boolean equals(Object var1) throws { try { return (Boolean)super.h.invoke(this, m1, new Object[]{var1}); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } } public final String demo() throws { try { return (String)super.h.invoke(this, m3, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } public final String toString() throws { try { return (String)super.h.invoke(this, m2, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } public final int hashCode() throws { try { return (Integer)super.h.invoke(this, m0, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } static { try { m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object")); m3 = Class.forName("com.proxy.DemoService").getMethod("demo"); m2 = Class.forName("java.lang.Object").getMethod("toString"); m0 = Class.forName("java.lang.Object").getMethod("hashCode"); } catch (NoSuchMethodException var2) { throw new NoSuchMethodError(var2.getMessage()); } catch (ClassNotFoundException var3) { throw new NoClassDefFoundError(var3.getMessage()); } } }
-
CGLB代理
CGLB代理无论目标对象是否有接口,都可以进行代理;底层是通过一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。
使用CGLB动态代理的步骤:
- 1、实现方法拦截器MethodInterceptor接口;
- 2、通过Enhancer类获取生成代理对象;先创建Enhancer类实例,设置目标类(父类),设置回调对象(我自定义的MethodInterceptor),enhancer.create()生成代理对象;
- 3、通过代理对象调用目标方法;
// 1、创建目标类 public class DemoService { public DemoService(){ System.out.println("DemoServiceImpl 构造函数"); } public String demo() { System.out.println("---------------DemoServiceImpl demo"); return "DemoServiceImpl demo"; } } // 2、实现cglb包下的MethodInterceptor接口自定义方法拦截 public class MyMethodInterceptor implements MethodInterceptor { /** * sub:cglib生成的代理对象 * method:被代理对象方法 * objects:方法入参 * methodProxy: 代理方法 */ @Override public Object intercept(Object sub, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("==============代理前=============="); Object invokeSuper = methodProxy.invokeSuper(sub, objects); System.out.println("==============代理后=============="); return invokeSuper; } } // 3、测试 public class CGLBProxyDemo { public static void main(String[] args) { // 代理类class文件存入本地方便我们反编译查看源码 System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "E:\\Workspace\\BaseDemo\\com\\sun\\cglbproxy"); // 通过CGLIB动态代理获取代理对象的过程 Enhancer enhancer = new Enhancer(); // 设置enhancer对象的父类 enhancer.setSuperclass(DemoService.class); // 设置enhancer的回调对象 enhancer.setCallback(new MyMethodInterceptor()); // 创建代理对象 DemoService proxy= (DemoService)enhancer.create(); // 通过代理对象调用目标方法 proxy.demo(); } }
CGLB代理生成的class有三个,其中一个内容如下;可以看到
DemoService$$EnhancerByCGLIB$$1b778719
是继承目标类,即CGLB代理生成的是目标类的子类
。public class DemoService$$EnhancerByCGLIB$$1b778719 extends DemoService implements Factory { private boolean CGLIB$BOUND; private static final ThreadLocal CGLIB$THREAD_CALLBACKS; private static final Callback[] CGLIB$STATIC_CALLBACKS; private MethodInterceptor CGLIB$CALLBACK_0; private static final Method CGLIB$demo$0$Method; private static final MethodProxy CGLIB$demo$0$Proxy; private static final Object[] CGLIB$emptyArgs; private static final Method CGLIB$finalize$1$Method; private static final MethodProxy CGLIB$finalize$1$Proxy; private static final Method CGLIB$equals$2$Method; private static final MethodProxy CGLIB$equals$2$Proxy; private static final Method CGLIB$toString$3$Method; private static final MethodProxy CGLIB$toString$3$Proxy; private static final Method CGLIB$hashCode$4$Method; private static final MethodProxy CGLIB$hashCode$4$Proxy; private static final Method CGLIB$clone$5$Method; private static final MethodProxy CGLIB$clone$5$Proxy; static void CGLIB$STATICHOOK1() { CGLIB$THREAD_CALLBACKS = new ThreadLocal(); CGLIB$emptyArgs = new Object[0]; Class var0 = Class.forName("com.cglbproxy.DemoService$$EnhancerByCGLIB$$1b778719"); Class var1; Method[] var10000 = ReflectUtils.findMethods(new String[]{"finalize", "()V", "equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"}, (var1 = Class.forName("java.lang.Object")).getDeclaredMethods()); CGLIB$finalize$1$Method = var10000[0]; CGLIB$finalize$1$Proxy = MethodProxy.create(var1, var0, "()V", "finalize", "CGLIB$finalize$1"); CGLIB$equals$2$Method = var10000[1]; CGLIB$equals$2$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$2"); CGLIB$toString$3$Method = var10000[2]; CGLIB$toString$3$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$3"); CGLIB$hashCode$4$Method = var10000[3]; CGLIB$hashCode$4$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$4"); CGLIB$clone$5$Method = var10000[4]; CGLIB$clone$5$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$5"); CGLIB$demo$0$Method = ReflectUtils.findMethods(new String[]{"demo", "()Ljava/lang/String;"}, (var1 = Class.forName("com.cglbproxy.DemoService")).getDeclaredMethods())[0]; CGLIB$demo$0$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "demo", "CGLIB$demo$0"); } final String CGLIB$demo$0() { return super.demo(); } public final String demo() { MethodInterceptor var10000 = this.CGLIB$CALLBACK_0; if (var10000 == null) { CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_0; } return var10000 != null ? (String)var10000.intercept(this, CGLIB$demo$0$Method, CGLIB$emptyArgs, CGLIB$demo$0$Proxy) : super.demo(); } final void CGLIB$finalize$1() throws Throwable { super.finalize(); } protected final void finalize() throws Throwable { MethodInterceptor var10000 = this.CGLIB$CALLBACK_0; if (var10000 == null) { CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_0; } if (var10000 != null) { var10000.intercept(this, CGLIB$finalize$1$Method, CGLIB$emptyArgs, CGLIB$finalize$1$Proxy); } else { super.finalize(); } } final boolean CGLIB$equals$2(Object var1) { return super.equals(var1); } public final boolean equals(Object var1) { MethodInterceptor var10000 = this.CGLIB$CALLBACK_0; if (var10000 == null) { CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_0; } if (var10000 != null) { Object var2 = var10000.intercept(this, CGLIB$equals$2$Method, new Object[]{var1}, CGLIB$equals$2$Proxy); return var2 == null ? false : (Boolean)var2; } else { return super.equals(var1); } } final String CGLIB$toString$3() { return super.toString(); } public final String toString() { MethodInterceptor var10000 = this.CGLIB$CALLBACK_0; if (var10000 == null) { CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_0; } return var10000 != null ? (String)var10000.intercept(this, CGLIB$toString$3$Method, CGLIB$emptyArgs, CGLIB$toString$3$Proxy) : super.toString(); } final int CGLIB$hashCode$4() { return super.hashCode(); } public final int hashCode() { MethodInterceptor var10000 = this.CGLIB$CALLBACK_0; if (var10000 == null) { CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_0; } if (var10000 != null) { Object var1 = var10000.intercept(this, CGLIB$hashCode$4$Method, CGLIB$emptyArgs, CGLIB$hashCode$4$Proxy); return var1 == null ? 0 : ((Number)var1).intValue(); } else { return super.hashCode(); } } final Object CGLIB$clone$5() throws CloneNotSupportedException { return super.clone(); } protected final Object clone() throws CloneNotSupportedException { MethodInterceptor var10000 = this.CGLIB$CALLBACK_0; if (var10000 == null) { CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_0; } return var10000 != null ? var10000.intercept(this, CGLIB$clone$5$Method, CGLIB$emptyArgs, CGLIB$clone$5$Proxy) : super.clone(); } public static MethodProxy CGLIB$findMethodProxy(Signature var0) { String var10000 = var0.toString(); switch(var10000.hashCode()) { case -1574182249: if (var10000.equals("finalize()V")) { return CGLIB$finalize$1$Proxy; } break; case -508378822: if (var10000.equals("clone()Ljava/lang/Object;")) { return CGLIB$clone$5$Proxy; } break; case -415285202: if (var10000.equals("demo()Ljava/lang/String;")) { return CGLIB$demo$0$Proxy; } break; case 1826985398: if (var10000.equals("equals(Ljava/lang/Object;)Z")) { return CGLIB$equals$2$Proxy; } break; case 1913648695: if (var10000.equals("toString()Ljava/lang/String;")) { return CGLIB$toString$3$Proxy; } break; case 1984935277: if (var10000.equals("hashCode()I")) { return CGLIB$hashCode$4$Proxy; } } return null; } public DemoService$$EnhancerByCGLIB$$1b778719() { CGLIB$BIND_CALLBACKS(this); } public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) { CGLIB$THREAD_CALLBACKS.set(var0); } public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] var0) { CGLIB$STATIC_CALLBACKS = var0; } private static final void CGLIB$BIND_CALLBACKS(Object var0) { DemoService$$EnhancerByCGLIB$$1b778719 var1 = (DemoService$$EnhancerByCGLIB$$1b778719)var0; if (!var1.CGLIB$BOUND) { var1.CGLIB$BOUND = true; Object var10000 = CGLIB$THREAD_CALLBACKS.get(); if (var10000 == null) { var10000 = CGLIB$STATIC_CALLBACKS; if (var10000 == null) { return; } } var1.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])var10000)[0]; } } public Object newInstance(Callback[] var1) { CGLIB$SET_THREAD_CALLBACKS(var1); DemoService$$EnhancerByCGLIB$$1b778719 var10000 = new DemoService$$EnhancerByCGLIB$$1b778719(); CGLIB$SET_THREAD_CALLBACKS((Callback[])null); return var10000; } public Object newInstance(Callback var1) { CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1}); DemoService$$EnhancerByCGLIB$$1b778719 var10000 = new DemoService$$EnhancerByCGLIB$$1b778719(); CGLIB$SET_THREAD_CALLBACKS((Callback[])null); return var10000; } public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) { CGLIB$SET_THREAD_CALLBACKS(var3); DemoService$$EnhancerByCGLIB$$1b778719 var10000 = new DemoService$$EnhancerByCGLIB$$1b778719; switch(var1.length) { case 0: var10000.<init>(); CGLIB$SET_THREAD_CALLBACKS((Callback[])null); return var10000; default: throw new IllegalArgumentException("Constructor not found"); } } public Callback getCallback(int var1) { CGLIB$BIND_CALLBACKS(this); MethodInterceptor var10000; switch(var1) { case 0: var10000 = this.CGLIB$CALLBACK_0; break; default: var10000 = null; } return var10000; } public void setCallback(int var1, Callback var2) { switch(var1) { case 0: this.CGLIB$CALLBACK_0 = (MethodInterceptor)var2; default: } } public Callback[] getCallbacks() { CGLIB$BIND_CALLBACKS(this); return new Callback[]{this.CGLIB$CALLBACK_0}; } public void setCallbacks(Callback[] var1) { this.CGLIB$CALLBACK_0 = (MethodInterceptor)var1[0]; } static { CGLIB$STATICHOOK1(); } }