關閉→
當前位置:知科普>IT科技>enhancer - java

enhancer - java

知科普 人氣:3.82K

<link rel="stylesheet" href="https://js.how234.com/third-party/SyntaxHighlighter/shCoreDefault.css" type="text/css" /><script type="text/javascript" src="https://js.how234.com/third-party/SyntaxHighlighter/shCore.js"></script><script type="text/javascript"> SyntaxHighlighter.all(); </script>

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文件格式和指令集都很熟悉。

java enhancer

另外,在使用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);

TAG標籤:#java #enhancer #