<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          jBeanBoxIOC/AOP工具

          聯(lián)合創(chuàng)作 · 2023-09-30 06:58

          jBeanBox

          License: Apache 2.0

          jBeanBox是一個(gè)微形但功能較齊全的IOC/AOP工具,除了引入的第三方庫(kù)之外,它的核心只有十多個(gè)類,源碼只有1500行左右。它運(yùn)用了“Box”編程模式,利用純粹的Java類作為配置。jBeanBox運(yùn)行于JDK1.6或以上。
          jBeanBox的開發(fā)目的是要克服其它IOC/AOP工具的一些問題:

          1. Spring: 源碼臃腫,Java方式的配置不靈活,在動(dòng)態(tài)配置、配置的繼承上有問題、啟動(dòng)慢、非單例模式時(shí)性能極差。
          2. Guice: 源碼略臃腫(200個(gè)類),使用不太方便,對(duì)Bean的生命周期支持不好。
          3. Feather:源碼極簡(jiǎn)(幾百行),但功能不全,只是一個(gè)DI工具,不支持AOP。
          4. Dagger: 源碼略臃腫(300個(gè)類),編譯期靜態(tài)注入,使用略不便,不支持AOP。
          5. Genie: 這是ActFramework的內(nèi)核,只是DI工具,不支持AOP。

          如何在項(xiàng)目中使用jBeanBox?

          手工下載jbeanbox-2.4.8.jar放到項(xiàng)目的類目錄,或在pom.xml中加入以下配置:

          
            
              
             
              com.github.drinkjava2
             
              
             
              jbeanbox
             
              
             
              2.4.8
              
          
            

          jBeanBox不依賴于任何第三方庫(kù),為避免包沖突,它將用到的CGLIB等第三方庫(kù)以源碼內(nèi)嵌方式包含在項(xiàng)目中。jBeanBox的jar包尺寸較大,約為750K,如果用不到AOP功能,可以只使用它的DI內(nèi)核,稱為"jBeanBoxDI", 只有49k大小,將上面artifactId中的jbeanbox改成jbeanboxdi即可。jBeanBoxDI項(xiàng)目詳見jbeanboxdi子目 錄。

          第一個(gè)jBeanBox演示:

          以下演示了9種不同的注入方式:

          public class HelloWorld {
            public static class User {
              String name;    
              
              public User() {   }    
              
              @VALUE("User1")  
              public User(String name) { this.name = name; }   
              
              void setName(String name) { this.name = name; } 
              
              void init() {this.name = "User6";}    
              
              @PreDestroy 
              void end() {this.name= "User9";}
            }
          
            public static class UserBox extends BeanBox {
               Object create() {return new User("User2");}
            }
          
            public static class H7 extends UserBox {{setAsValue("User7");}}
           
            public static void main(String[] args) {
              User u1 = JBEANBOX.getInstance(User.class);
              User u2 = JBEANBOX.getBean(UserBox.class);
              User u3 = JBEANBOX.getBean(new BeanBox().injectConstruct(User.class, String.class, value("User3")));
              User u4 = JBEANBOX.getBean(new BeanBox(User.class).injectValue("name", "User4" ));
              User u5 = JBEANBOX
                  .getBean(new BeanBox(User.class).injectMethod("setName", String.class, value("User5")));
              User u6 = JBEANBOX.getBean(new BeanBox().setBeanClass(User.class).setPostConstruct("init"));
              
              BeanBoxContext ctx = new BeanBoxContext(); 
              Interceptor aop=new MethodInterceptor() { 
                public Object invoke(MethodInvocation invocation) throws Throwable { 
                  invocation.getArguments()[0]="User8";
                  return invocation.proceed();
                }
              };
              User u7 = ctx.bind(String.class, "7").bind("7", H7.class)
                .getBean(ctx.getBeanBox(User.class).addMethodAop(aop, "setName",String.class).injectField("name", autowired())); 
              System.out.println(u1.name); //Result: User1
              System.out.println(u2.name); //Result: User2
              System.out.println(u3.name); //Result: User3
              System.out.println(u4.name); //Result: User4
              System.out.println(u5.name); //Result: User5
              System.out.println(u6.name); //Result: User6
              System.out.println(u7.name); //Result: User7
              u7.setName("");
              System.out.println(u7.name); //Result: User8
              ctx.close();
              System.out.println(u7.name); //Result: User9 
            }
          } 
          

          這個(gè)例子的輸出結(jié)果是依次打印出“User1” 、“User2”...到“User9”。下面遂一解釋:

          1. 利用了@VALUE("User1")注解,進(jìn)行了構(gòu)造器注入
          2. UserBox是一個(gè)jBeanBox的純Java配置類,這個(gè)Java類是一個(gè)純粹的Java類(不象Spring中的Java配置類是一個(gè)非 常特殊的類,它在運(yùn)行期會(huì)產(chǎn)生一個(gè)代理類),可以運(yùn)用類的繼承、方法重寫等常見設(shè)計(jì)模式。 在這個(gè)示例里它的create方法手工生成了一個(gè)User("User2")對(duì)象。
          3. 第三個(gè)是動(dòng)態(tài)生成一個(gè)BeanBox配置,動(dòng)態(tài)配置它的構(gòu)造器注入,注入值為"User3"。
          4. 第四個(gè)也是動(dòng)態(tài)配置,演示了字段注入,注入值為常量"User4".
          5. 第五個(gè)是方法注入的演示,注入?yún)?shù)依次為:方法名、參數(shù)類型們、實(shí)際參數(shù)們。
          6. 第六個(gè)是setPostConstruct注入,等效于@PostConstruct注解,即Bean生成后立即執(zhí)行的方法為init()方法。
          7. 第七個(gè)比較復(fù)雜,ctx是一個(gè)新的上下文實(shí)例,它先獲取User.class的固定配置,然后給它的setName方法添加一個(gè)AOP切面,然后 注入"name"字段為autowired類型,也就是說String類型,不過在此之前String類被綁定到字符串"7",字符串"7"又綁定到 H2.class,H7又繼承于UserBox,UserBox又返回"User2",然而都是浮云,因?yàn)镠7本身被配置成一個(gè)值類型"User7",于 是最后輸出結(jié)果是“User7”。
          8. 第八個(gè)比較簡(jiǎn)單,因?yàn)閟etName方法被添加了一個(gè)AOP攔截器,參數(shù)被改成了"User8"。
          9. 第九個(gè)是因?yàn)閏tx這個(gè)上下文結(jié)束,所有單例被@PreDestroy標(biāo)注的方法會(huì)執(zhí)行,這是一個(gè)標(biāo)準(zhǔn)JSR330注解。

          上例除了一頭一尾外,主要演示了jBeanBox的Java方法配置,Java方法即可以動(dòng)態(tài)執(zhí)行,也可以在定義好的BeanBox類中作為固定配 置執(zhí)行,固定的配置可以打下配置的基調(diào),當(dāng)固定配置需要變動(dòng)時(shí)可以用同樣的Java方法來進(jìn)行調(diào)整(因?yàn)楸緛砭褪峭粋€(gè)BeanBox對(duì)象)甚至臨時(shí)創(chuàng)建 出新的配置,所以jBeanBox同時(shí)具有了固定配置和動(dòng)態(tài)配置的優(yōu)點(diǎn)。另外當(dāng)沒有源碼時(shí),例如配置第三方庫(kù)的實(shí)例,這時(shí)所有的注解方式配置都用不上,唯 一能用的只有Java配置方式。

          上例中的value()方法是從JBEANBOX類中靜態(tài)引入的全局方法,這個(gè)示例的源碼位于單元測(cè)試目錄下的HelloWorld.java。

          jBeanBox注解方式配置

          jBeanBox不光支持Java方式配置,還支持注解方式配置,它支持以下注解:
          @INJECT 類似于JSR中的@Inject注解,但允許添加目標(biāo)類作為參數(shù)
          @POSTCONSTRUCT 等同于JSR中的@PostConstruct注解
          @PREDESTROY 等同于JSR中的@PreDestroy注解
          @VALUE 類似于Spring中的@Value注解
          @PROTOTYPE 等同于Spring中的@Prototype注解
          @AOP 用于自定義AOP注解,詳見AOP一節(jié)

          jBeanBox還能自動(dòng)識(shí)別并支持以下JSR及Spring的注解:
          JSR的注解:@PostConstruct, @PreDestroy, @Inject, @Singleton, @scope(“prototype”), @scope(“singleton”)
          Spring的注解:@Autowired @Prototype

          因?yàn)樽⒔夥绞脚渲么蠹叶挤浅J煜ぃ@里就不作詳細(xì)介紹了,在jBeanBox\test目錄下能找到一 個(gè)"AnnotationInjectTest.java"文件,演示了各種注解方式配置的使用。另外還可以調(diào)用 ctx.setAllowSpringJsrAnnotation(false)去禁用JSR、Spring注解,也可以調(diào)用 ctx.setAllowAnnotation(false)去禁用所有注解(也就是說只能用Java方式配置了)。

          關(guān)于注解方式配置,jBeanBox與其它IOC工具不同點(diǎn)在于:它不支持@Qualifer、@Name、@Provider這三個(gè)JSR330注解,這是因?yàn)楣P者認(rèn)為這3個(gè)注解在jBeanBox中可以用已有注解實(shí)現(xiàn),如:

          @Inject @Named("JDBC-URL")  private String url;
          在jBeanBox中可以用以下方式替代:
          @INJECT(JDBC_URL.class)  private String url; //其中JDBC_URL.class是一個(gè)BeanBox類  
          或
          @VALUE("$JDBC-URL")  private String url; //$JDBC-URL值可以通過配置BeanBoxContext中的ValueTranslator來解釋。 
          
          又如:
          @Named("p") public class Person {}
          在jBeanBox中看來,Person類已經(jīng)有了唯一的ID: Person.class, 無需再定義一個(gè)多余的“P”作為ID,所有靜態(tài)定義的類,它的類本身就是唯一的ID。jBeanBox對(duì)于靜態(tài)定義的類,默認(rèn)均為單例類,所以每次ctx.getBean(Person.class)都會(huì)獲得同一個(gè)單例對(duì)象。  
          

          @Named的問題是它是字符串類型的,無法利用IDE快速定位到配置文件,當(dāng)項(xiàng)目配置很多時(shí),不利于維護(hù)。
          jBeanBox是一個(gè)無需定義Bean ID的IOC工具,注意:如果是手工動(dòng)態(tài)創(chuàng)建的BeanBox配置,默認(rèn)均為非單例類。如果用setSingleton(true)方法硬改成單例,那問 題來了,它的ID是什么? 很簡(jiǎn)單,它的唯一ID就是這個(gè)動(dòng)態(tài)創(chuàng)建的配置實(shí)例本身。BeanBox box1=new BeanBox(A.class).setSingeton(true), 則每次ctx.getBeanBox(box1)就會(huì)獲得同一個(gè)A類型的單例對(duì)象。當(dāng)然,也可以用ctx.bind("id1",box1),則相當(dāng)于手 工給它綁定了一個(gè)ID值"id1",可以用getBean("id1")來獲取它。jBeanBox沒有自動(dòng)掃描、預(yù)創(chuàng)建單例之類的功能,所以它的啟動(dòng)非 ??焖?。如果有人有自動(dòng)掃描、預(yù)創(chuàng)建單例、預(yù)綁定ID名之類的需求,必須手工編寫一個(gè)工具類來實(shí)現(xiàn)這個(gè)目的(jBeanBox暫不提供),例如在程序運(yùn)行 開始時(shí)調(diào)用一下ctx.getBean(A.class)就會(huì)在上下文中暫存一個(gè)A的單例類,下次訪問時(shí)會(huì)直接從緩存中取。

          jBeanBox的Java方式配置

          示例一只是籠統(tǒng)演示了一下jBeanBox的Java方式配置,現(xiàn)在再回過頭來詳細(xì)介紹一下它的Java方式配置:

          • setAsValue(Object) 將當(dāng)前BeanBox配置成一個(gè)常量值,等同于setTarget(Obj)+setPureVale(true)
          • setPrototype(boolean) 如參數(shù)為true時(shí)表示它是一個(gè)非單例,與setSingleton方法作用相反
          • injectConstruct(Class, Object...) 設(shè)定構(gòu)造器注入,參數(shù)分別是類、構(gòu)造器參數(shù)類型們、參數(shù)們
          • injectMethod(String, Object...) 設(shè)定某個(gè)方法注入,參數(shù)分別是方法名、參數(shù)類型們、參數(shù)們
          • addAopToMethod(Object, Method) 對(duì)某個(gè)方法添加AOP,參數(shù)分別是AOP類或?qū)嵗⒎椒?/li>
          • addMethodAop(Object, String, Class...) 對(duì)某個(gè)方法添加AOP,參數(shù)分別是AOP類或?qū)嵗⒎椒?、參?shù)類型們
          • addBeanAop(Object, String) 對(duì)整個(gè)Bean添加AOP,參數(shù)分別是AOP類或?qū)嵗⒎椒ㄒ?guī)則(如"setUser*"),
          • setPostConstruct(String) 設(shè)定一個(gè)PostConstruct方法名,效果等同與@PostConstruct注解
          • setPreDestroy(String) 設(shè)定一個(gè)PreDestroy方法名,效果等同與@PreDestroy注解
          • injectField(String, BeanBox) 注入一個(gè)字段,參數(shù)是字段名、BeanBox實(shí)例,它的等效注解是@INJECT
          • setProperty(String, Object) 等同于injectValue方法
          • injectValue(String, Object) 注入一個(gè)字段,參數(shù)是字段名、對(duì)象實(shí)例,可與它類比的注解是@VALUE
          • setTarget(Object) 注定當(dāng)前Bean的目標(biāo),另外當(dāng)bind("7",User.class)時(shí),setTarget("7")就等同于setTarget(User.class)
          • setPureValue(boolean) 表示target不再是目標(biāo)了,而是作為純值返回,上行的"7"就會(huì)返回字符串"7"
          • setBeanClass(Class) 設(shè)定當(dāng)前BeanBox的最終目標(biāo)類,所有的配置都是基于這個(gè)類展開
          • setSingleton(Boolean) 與setPrototype作用相反
          • setConstructor(Constructor) 設(shè)定一個(gè)構(gòu)造器
          • setConstructorParams(BeanBox[]) 設(shè)定構(gòu)造器的參數(shù),與上行聯(lián)用
          • setPostConstruct(Method) 設(shè)定一個(gè)PostConstruct方法,效果等同與@PostConstruct注解
          • setPreDestroy(Method) 設(shè)定一個(gè)PreDestroy方法名,效果等同與@PreDestroy注解

          Java方式配置,對(duì)于BeanBox來說,還有兩個(gè)特殊的方法create和config,如下示例:

          public static class DemoBox extends BeanBox {
          
          		public Object create(Caller caller) {
          			A a = new A();
          			a.field1 = caller.getBean(B.class);
          			return a;
          		}
          
          		public void config(Object o, Caller caller) {
          			((A) o).field2 = caller.getBean(C.class);
          		}
          	}
          

          上例表示DemoBox中創(chuàng)建的Bean是由create方法來生成,由config方法來修改。create和config方法中的Caller參數(shù)可以省略,如果不需要利用這個(gè)Caller參數(shù)進(jìn)行加載其它Bean的話。

          jBeanBox的AOP(面向切面編程)

          jBeanBox功能大都可以用Java配置或注解配置兩種方式來實(shí)現(xiàn),同樣地,它對(duì)AOP的支持也有兩種方式:

          Java方式AOP配置

          • someBeanBox.addMethodAop(Object, String, Class...) 對(duì)某個(gè)方法添加AOP,參數(shù)分別是AOP類或?qū)嵗?、方法名、參?shù)類型們
          • someBeanBox.addBeanAop(Object, String) 對(duì)整個(gè)Bean添加AOP,參數(shù)分別是AOP類或?qū)嵗?、方法?guī)則(如"setUser*")
          • someBeanBoxContext.addGlobalAop(Object, Object, String);對(duì)整個(gè)上下文添加AOP規(guī)則,參數(shù)分別是AOP類或?qū)嵗?、類或類名?guī)則、方法名規(guī)則。
            以上三個(gè)方法分別對(duì)應(yīng)三種不同級(jí)別的AOP規(guī)則,第一個(gè)方法只針對(duì)方法,第二個(gè)方法針對(duì)整個(gè)類,第三個(gè)方法針對(duì)整個(gè)上下文。以下是一個(gè)AOP的Java配置示例:
          public static class AopDemo1 {
          		String name;
          		String address;
          		String email;
                  //getter & setters...
          	}
          
          	public static class MethodAOP implements MethodInterceptor { 
          		public Object invoke(MethodInvocation invocation) throws Throwable {
          			invocation.getArguments()[0] = "1";
          			return invocation.proceed();
          		}
          	}
          
          	public static class BeanAOP implements MethodInterceptor { 
          		public Object invoke(MethodInvocation invocation) throws Throwable {
          			invocation.getArguments()[0] = "2";
          			return invocation.proceed();
          		}
          	}
          
          	public static class GlobalAOP implements MethodInterceptor {
          		@Override
          		public Object invoke(MethodInvocation invocation) throws Throwable {
          			invocation.getArguments()[0] = "3";
          			return invocation.proceed();
          		}
          	}
          
          	public static class AopDemo1Box extends BeanBox {
          		{
          			this.injectConstruct(AopDemo1.class, String.class, value("0"));
          			this.addMethodAop(MethodAOP.class, "setName", String.class);
          			this.addBeanAop(BeanAOP.class, "setAddr*");
          		}
          	}
          
          	@Test
          	public void aopTest1() {
          		JBEANBOX.bctx().bind("3", GlobalAOP.class);
          		JBEANBOX.bctx().addGlobalAop("3", AopDemo1.class, "setEm*");
          		AopDemo1 demo = JBEANBOX.getBean(AopDemo1Box.class);
          		demo.setName("--");
          		Assert.assertEquals("1", demo.name);
          		demo.setAddress("--");
          		Assert.assertEquals("2", demo.address);
          		demo.setEmail("--");
          		Assert.assertEquals("3", demo.email);
          	}
          

          上面的命名規(guī)則采用“*”做為模糊匹配字符,代表任意長(zhǎng)度、任意字符。

          注解方式AOP配置

          注解方式AOP只有兩種類型,針對(duì)方法的和針對(duì)類的,沒有針對(duì)上下文的。 注解方式需要用到一個(gè)特殊的注解@AOP,它是用來自定義自已的AOP注解用的,使用示例如下:

          public static class Interceptor1 implements MethodInterceptor {
          		public Object invoke(MethodInvocation invocation) throws Throwable {
          			invocation.getArguments()[0] = "1";
          			return invocation.proceed();
          		}
          	}
          
          	public static class Interceptor2 implements MethodInterceptor {
          		public Object invoke(MethodInvocation invocation) throws Throwable {
          			invocation.getArguments()[0] = "2";
          			return invocation.proceed();
          		}
          	}
          
          	@Retention(RetentionPolicy.RUNTIME)
          	@Target({ ElementType.TYPE })
          	@AOP
          	public static @interface MyAop1 {
          		public Class value() default Interceptor1.class;
          
          		public String method() default "setNa*";
          	}
          
          	@Retention(RetentionPolicy.RUNTIME)
          	@Target({ ElementType.METHOD })
          	@AOP
          	public static @interface MyAop2 {
          		public Class value() default Interceptor2.class;
          	}
          
          	@MyAop1
          	public static class AopDemo1 {
          		String name;
          		String address;
          
          		public void setName(String name) {
          			this.name = name;
          		}
          
          		@MyAop2
          		public void setAddress(String address) {
          			this.address = address;
          		}
          	}
          
          	@Test
          	public void aopTest1() {
          		AopDemo1 demo = JBEANBOX.getBean(AopDemo1.class);
          		demo.setName("--");
          		Assert.assertEquals("1", demo.name);
          		demo.setAddress("--");
          		Assert.assertEquals("2", demo.address);
          	}
          

          本文所說的AOP是針對(duì)Aop alliance聯(lián)盟標(biāo)準(zhǔn)的接口來說的,它已經(jīng)被包含在jBeanBox中,無需再單獨(dú)引入(當(dāng)然重復(fù)引入也不會(huì)有問題)。Aop alliance聯(lián)盟標(biāo)準(zhǔn)是比較有用的一個(gè)接口,實(shí)現(xiàn)了各種AOP實(shí)現(xiàn)之間的互換性,基于它,jBeanBox可以替換掉Spring的內(nèi)核而使用它的聲 明式事務(wù),這種互換性能夠?qū)崿F(xiàn)的前提就是因?yàn)镾pring的聲明式事務(wù)實(shí)現(xiàn)(如TransactionInterceptor)也實(shí)現(xiàn)了Aop alliance聯(lián)盟標(biāo)準(zhǔn)接口MethodInterceptor。

          jBeanBox從2.4.8版本起,AOP功能大副削減,去掉了不常用的前置、后置、異常切面功能,只保留了支持AOP alliance聯(lián)盟標(biāo)準(zhǔn)接口MethodInterceptor的功能(注意在CGLIB也有一個(gè)同名的接口,不要混淆)。實(shí)現(xiàn)了 MethodInterceptor接口的類,通常稱為Interceptor,但在jBeanBox中圖省事,也把它稱為AOP,畢竟寫成 addBeanAop要比寫成addBeanInterceptor簡(jiǎn)潔一些。

          關(guān)于循環(huán)依賴

          jBeanBox具備循環(huán)依賴檢測(cè)功能,如果發(fā)現(xiàn)循環(huán)依賴注入(如A構(gòu)造器中注入B,B的構(gòu)造器中又需要注入A),將會(huì)拋出BeanBoxException運(yùn)行時(shí)異常。 但是,以下這種字段或方法中出現(xiàn)的循環(huán)依賴注入在jBeanBox中是允許的:

          public static class A {
          		@Inject
          		public B b;
          	}
          
          public static class B {
          		@Inject
          		public A a;
          	}
          
          A a = JBEANBOX.getBean(A.class);
          Assert.assertTrue(a == a.b.a);//true
          

          jBeanBox支持多上下文和Bean生命周期

          jBeanBox支持多個(gè)上下文實(shí)例(BeanBoxContext),每個(gè)上下文實(shí)例都是互不干攏的。例如一個(gè)User.class可以在3個(gè)上 下文中各自用不同的配置方式(注解、Java)生成3個(gè)單例,這3個(gè)“單例”都是相對(duì)于當(dāng)前上下文唯一的,它們的屬性與各自的配置有關(guān)。

          JBEANBOX.getBean()方法是利用了一個(gè)缺省的全局上下文,可以用JBEANBOX.bctx()方法來獲取,所以如果一個(gè)項(xiàng)目中不 需要用到多個(gè)上下文,可以直接使用JBEANBOX.getBean()方法來獲取實(shí)例,這樣可以節(jié)省一行創(chuàng)建一個(gè)新上下文的代碼。

          BeanBoxContext的每個(gè)實(shí)例都在內(nèi)部維護(hù)著配置信息、單例緩存等,在BeanBoxContext實(shí)例的close方法被調(diào)用后,它的 配置信息和單例被清空,當(dāng)然,在清空之前,所有單例類的PreDestroy方法(如果有的話)被調(diào)用運(yùn)行。所以對(duì)于需要回調(diào)PreDestroy方法的 上下文來說,在關(guān)閉時(shí)不要忘了調(diào)用close方法。對(duì)于缺省的全局上下文來說就是JBEANBOX.close()方法。

          BeanBoxContext的常用方法詳解:

          • reset() 這個(gè)靜態(tài)方法重置所有靜態(tài)全局配置,并調(diào)用缺省上下文實(shí)例的close方法。
          • close() 先調(diào)用當(dāng)前上下文緩存中單例實(shí)例的PreDestroy方法(如果有的話),然后清空當(dāng)前上下文的緩存。
          • getBean(Object) 根據(jù)目標(biāo)對(duì)象(可以是任意對(duì)象類型),返回一個(gè)Bean,如果找不到則拋出異常
          • getInstance(Class) 根據(jù)目標(biāo)類T,返回一個(gè)T類型的實(shí)例, 如果找不到則拋出異常
          • getBean(Object, boolean) 根據(jù)目標(biāo)對(duì)象,返回一個(gè)Bean, 第二個(gè)參數(shù)為false時(shí)如果找不到則返回Empty.class
          • getInstance(Class, boolean) 根據(jù)目標(biāo)類T,返回一個(gè)T類型的實(shí)例, 第二個(gè)參數(shù)為false時(shí)如果找不到則返回Empty.class
          • bind(Object, Object) 給目標(biāo)類綁定一個(gè)ID,例如:ctx.bind("A","B").bind("B".C.class),則以后可以用getBean("A")獲取C的實(shí)例
          • addGlobalAop(Object, String, String) 在當(dāng)前上下文環(huán)境添加一個(gè)AOP(詳見AOP一節(jié)),第二個(gè)參數(shù)為類名模糊匹配規(guī)則,如"com.tom.*"或"*.tom"等,*號(hào)只允許出現(xiàn)在頭尾 (可以同時(shí)出現(xiàn),也可以一個(gè)不出現(xiàn)), 第三個(gè)參數(shù)為方法名模糊匹配規(guī)則,如"setUser*"或"*user"等。
          • addGlobalAop(Object, Class, String) 在當(dāng)前上下文環(huán)境添加一個(gè)AOP,第二個(gè)參數(shù)為根類,第三個(gè)參數(shù)為方法名模糊匹配規(guī)則
          • getBeanBox(Class) 獲取一個(gè)類的BeanBox實(shí)例,例如一個(gè)注解標(biāo)注的類,可以用這個(gè)方法獲取BeanBox實(shí)例,然后再添加、修改它的配置,這就是固定配置和動(dòng)態(tài)配置的結(jié)合運(yùn)用。
          • setAllowAnnotation(boolean) 設(shè)定是否允許讀取類中的注解,如果設(shè)為flase的話,則jBeanBox只允行使用純Java配置方式。默認(rèn)true。
          • setAllowSpringJsrAnnotation(boolean) 設(shè)定是否允先讀取類中JSR330/JSR350和Spring的部分注解,以實(shí)現(xiàn)兼容性。默認(rèn)true。
          • setValueTranslator(ValueTranslator) 設(shè)定對(duì)于@VALUE注解中的內(nèi)容,如何解析它,例如@VALUE("#user"),系統(tǒng)默認(rèn)返回"#user"字符串,如果需要不同的解析,例如讀取 property文本中的值,則需要自已設(shè)定一個(gè)實(shí)現(xiàn)了ValueTranslator接口的實(shí)例。

          jBeanBox的性能

          以下為jBeanBox的性能與其它IOC工具的對(duì)比(只對(duì)比DI注入功能,搭建一個(gè)由6個(gè)對(duì)象組成的實(shí)例樹),可見jBeanBox創(chuàng)建非單例的 速度大約為Guice的一半,但依然要比Spring快得多,是Spring的45倍左右。測(cè)試程序詳見:[di-benchmark](https://github.com/drinkjava2/di-benchmark)

          Runtime benchmark, fetch new bean for 500000 times:
          ---------------------------------------------------------
                               Vanilla|    31ms
                                 Guice|  1154ms
                               Feather|   624ms
                                Dagger|   312ms
                                 Genie|   609ms
                                  Pico|  4555ms
                        jBeanBoxNormal|  2075ms
                      jBeanBoxTypeSafe|  2371ms
                    jBeanBoxAnnotation|  2059ms
               SpringJavaConfiguration| 92149ms
               SpringAnnotationScanned| 95504ms
               
               
          Split Starting up DI containers & instantiating a dependency graph 4999 times:
          -------------------------------------------------------------------------------
                               Vanilla| start:     0ms   fetch:     0ms
                                 Guice| start:  1046ms   fetch:  1560ms
                               Feather| start:     0ms   fetch:   109ms
                                Dagger| start:    46ms   fetch:   173ms
                                  Pico| start:   376ms   fetch:   217ms
                                 Genie| start:   766ms   fetch:   247ms
                        jBeanBoxNormal| start:    79ms   fetch:   982ms
                      jBeanBoxTypeSafe| start:     0ms   fetch:   998ms
                    jBeanBoxAnnotation| start:     0ms   fetch:   468ms
               SpringJavaConfiguration| start: 51831ms   fetch:  1834ms
               SpringAnnotationScanned| start: 70712ms   fetch:  4155ms
          
          Runtime benchmark, fetch singleton bean for 5000000 times:
          ---------------------------------------------------------
                               Vanilla|    47ms
                                 Guice|  1950ms
                               Feather|   624ms
                                Dagger|  2746ms
                                 Genie|   327ms
                                  Pico|  3385ms
                        jBeanBoxNormal|   188ms
                      jBeanBoxTypeSafe|   187ms
                    jBeanBoxAnnotation|   171ms
               SpringJavaConfiguration|  1061ms
               SpringAnnotationScanned|  1045ms
          

          雖然IOC工具大多應(yīng)用在單例場(chǎng)合,性能大家都差不多(因?yàn)閺木彺嬷腥?,但是如果遇到必須生成非單例的場(chǎng)合,例如每次訪問生成一個(gè)新的頁(yè)面實(shí)例,這時(shí)候Spring就不夠看了, 至于啟動(dòng)速度,則更是慢到離譜了。

          以上就是對(duì)jBeanBox的介紹,沒有別的文檔了,因?yàn)楫吘顾暮诵脑创a也只有1千多行(第三方工具如CGLIB、JSR接口等不算在內(nèi)),有問題去看看它的源碼可能更簡(jiǎn)單一些。

          更多關(guān)于jBeanBox的用法還可以在jSqlBox項(xiàng)目中看到它的運(yùn)用(數(shù)據(jù)源的配置、聲明式事務(wù)示例等)。

          瀏覽 2
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          編輯 分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          編輯 分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日韩在线69 | 国产91美女被操网站 | 熟女午夜 | 欧美性xxx88 | 频逼特逼在线视频 |