java enhancer

作者:原创时间:2022-03-31
文档

java enhancer是什么,让我们一起了解一下?

Enhancer是cglib中使用频率很高的一个类,也是一个字节码增强器,可以用来为无接口的类创建代理,功能与java自带的Proxy类相似,会根据某个给定的类创建子类,并且所有非final的方法都带有回调钩子。

了解enhancer之前,我们要知道cglib是什么?

CGLIB是一个强大的高性能的代码生成包。它被许多AOP的框架(例如Spring AOP)使用,为他们提供方法的interception(拦截)。Hibernate也使用CGLIB来代理单端single-ended(多对一和一对一)关联。EasyMock通过使用模仿(moke)对象来测试java代码的包。它们都通过使用CGLIB来为那些没有接口的类创建模仿(moke)对象。
CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉。

另外,在使用CGLIB代理时需要注意的问题有哪些?

1、如果类是抽象类,只能调用已实现方法方法,如果调用抽象方法的时候会报java.lang.AbstractMethodError。 

2、要增强的类不能是final类,否则会报java.lang.IllegalArgumentException: Cannot subclass final class。

3、不能增强类的private方法,否则无法通过编译。

实战操作,enhancer常用的方法示例代码如下:

Enhancer enhancer = new Enhancer();
1、设置要继承的父类
enhancer.setSuperclass(superclass);
2、设置要实现的接口,这里需要实现EnhancedConfiguration,因为EnhancedConfiguration集成了BeanFactoryAware,则要生成对应的实现方法,用于在谁知工厂的时候做增强处理。具体详见ImportAwareBeanPostProcessor。
private static class ImportAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {
      private final BeanFactory beanFactory;
      public ImportAwareBeanPostProcessor(BeanFactory beanFactory) {
         this.beanFactory = beanFactory;
      }
      @Override
      public PropertyValues postProcessPropertyValues(
            PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) {
         // Inject the BeanFactory before AutowiredAnnotationBeanPostProcessor's
         // postProcessPropertyValues method attempts to autowire other configuration beans.
         if (bean instanceof EnhancedConfiguration) {
            ((EnhancedConfiguration) bean).setBeanFactory(this.beanFactory);
         }
         return pvs;
      }
      @Override
      public Object postProcessBeforeInitialization(Object bean, String beanName)  {
         if (bean instanceof ImportAware) {
            ImportRegistry ir = this.beanFactory.getBean(IMPORT_REGISTRY_BEAN_NAME, ImportRegistry.class);
            AnnotationMetadata importingClass = ir.getImportingClassFor(bean.getClass().getSuperclass().getName());
            if (importingClass != null) {
               ((ImportAware) bean).setImportMetadata(importingClass);
            }
         }
         return bean;
      }
   }
}
enhancer.setInterfaces(new Class[] {EnhancedConfiguration.class});
 
3、设置工厂这个还没用
enhancer.setUseFactory(false);
 
4、作用:指定生成Bean的名字一种策略 
    public class SpringNamingPolicy extends DefaultNamingPolicy {
       public static final SpringNamingPolicy INSTANCE = new SpringNamingPolicy();
       @Override
       protected String getTag() {
          return "BySpringCGLIB";
       }
    }
例:MathCalculator$$EnhancerBySpringCGLIB$$7e1949802152
 
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
 
5、设置用于从该生成器创建字节码的策略。默认情况下使用{@see DefaultGeneratorStrategy}的实例。
 
enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
 
6、在CGLib回调时可以设置对不同方法执行不同的回调逻辑,或者根本不执行回调 ,具体用法详见:CGLib中CallbackFilter介绍   链接在文章底部
enhancer.setCallbackFilter(CALLBACK_FILTER);
 
7、设置拦截器的类型
enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
 
8、设置增强器的数组,通过CallbackFilte来指定哪一个方法使用哪一个拦截器,关于Callback的类型具体详见: CGLib中Callback介绍 链接在文章底部
enhancer.setCallbacks(Callback[] callbacks);

以上就是小编今天的分享了,希望可以帮助到大家。

显示全文
java generic java enterprise java environment java epoll java error java escape java event java exchange java execute 微信群怎么找 怎么导出微信聊天记录 苹果手机怎么恢复出厂设置 qq怎么清理缓存和垃圾清理 朋友圈怎么转发 微信分组怎么删除 两个excel如何独立显示 excel怎么排序 计算机管理怎么打开 java jep java jetty java generator java future java encapsulation java empty java email java ehcache java echarts java formatter java ecc加密 java fork java foreach循环 java ear java flume java dynamic java dto java drools java flink java dowhile java flatmap java findfirst