1 Star 1 Fork 23

肌肉罗莎 / jBeanBox

forked from drinkjava2 / jBeanBox 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README
Apache-2.0

jBeanBox

License: Apache 2.0

jBeanBox是一个微形但功能较齐全的IOC/AOP工具,用于Java6或以上环境。

jBeanBox项目的定位:需要一个功能较全的IOC/AOP工具,但是又不想引入臃肿的Spring。

其它IOC/AOP工具的问题:

  1. Spring: 源码臃肿,Java方式的配置不灵活, 非单例模式时性能差。
  2. Guice: 源码臃肿(200多个类),手工绑定使用不方便,功能不全,如不支持PostConstruct、不支持类路径扫描。
  3. Feather:源码极简(几百行),但功能不全,只是DI工具,不支持AOP。
  4. Dagger: 源码略臃肿(300个类),编译期静态注入,性能最好,但使用不方便,不支持AOP。
  5. Genie: 这是ActFramework项目的内核,只是DI工具,不支持AOP。
  6. Nutz、jFinal等Web开发框架中也有IOC/AOP工具,但它们没有独立出来,并且没有考虑JSR330、AOP联盟等业界标准,通用性差。

jBeanBox的主要优点

  1. 功能较全,Java配置、注解配置、Bean生命周期支持、循环依赖检测和注入、AOP这些功能都具备。
  2. 源码简洁,除了引入的第三方库外,核心源码只有3000行左右,源码短小本身就说明了它架构的合理性。
  3. 采用原生Java作为配置,更简单易用。它的配置类BeanBox是一个纯Java类而不是一个代理类,可以作为静态配置存在,支持配置的继承、重写等特性, 也可以在运行期动态生成、修改,比Spring的Java配置方式更强大、灵活。
  4. 兼容性好,支持大多数JSR330、JSR250标准注解,并且兼容主要Spring注解。

如何在项目中使用jBeanBox?

手工在Maven站下载单个的jbeanbox-x.x.x.jar放到项目的类目录,或在pom.xml中加入以下配置:

<dependency>
    <groupId>com.github.drinkjava2</groupId>
    <artifactId>jbeanbox</artifactId>
    <version>4.0.0</version> <!-- Or newest version -->
</dependency>

jBeanBox只有单个jar包,不依赖于任何第三方库,为避免包冲突,它已经将用到的CGLIB等第三方库以源码内嵌的方式包含在了项目中。 jBeanBox的jar包尺寸较大,约为460K, 如果用不到AOP代理功能,可以只使用它的DI内核,称为"jBeanBoxDI", 只有约50k大小,将上面artifactId中的jbeanbox改成jbeanboxdi即可,jBeanBoxDI项目详见jbeanboxdi子目录。
顺便说一下,jSqlBox从4.0.0版起已经用源码内嵌的方式将jBeanBox包含到jSqlBox中去了,所以使用了jSqlBox的项目就不用再添加jBeanBox依赖了。jSqlBox是一个持久层工具,它利用jBeanBox的AOP功能提供声明式事务,而无需依赖Spring。

jBeanBox注解方式配置

jBeanBox有Java方式配置和注解方式配置两种使用方式。先用一张图来显示它支持的注解,以及与Spring、Guice的区别:
image
从上图可以看出,jBeanBox的功能较全,它除了自带注解外,还可以直接使用Spring及JSR330、JSR250的一些注解。红字部分为4.0.0版增加的功能。

jBeanBox自带以下注解(全部是大写):
@INJECT 类似JSR中的@Inject注解,但它有个附加的参数是允许添加可选的目标类或BeanBox配置类(见下文介绍)作为参数,如@INJECT(Book.class) 或 @INJECT(BookBox.class)
@POSTCONSTRUCT 等同于JSR中的@PostConstruct注解
@PREDESTROY 等同于JSR中的@PreDestroy注解
@VALUE 等同于Spring中的@Value注解, 参数将被解析为对应的值类型, 如@VALUE("3") int a; 参数将被解析为整数3。但与Spring不同的是jBeanBox不支持在@Value参数中的EL模板语法,需要通过自定义ValueTranslator实现。
@PROTOTYPE 等同于Spring中的@Prototype注解
@AOP 用于自定义AOP注解,详见AOP一节
@COMPONENT 用法等同于Spring中的@Component注解,它需要与jBeanBox的类扫描功能联用,用来自动发现注册指定类下的所有Bean类, 例如JBEANBOX.scanComponents("com.foo")可以扫描包"tom.foo"下的所有被@Component标注的类:
@NAMED 用法等同于JSR330中的@Named注解
@QUALIFILER 用法等同于JSR330或Spring中的@Qualifiler注解

jBeanBox默认工作在兼容模式,支持Spring和JSR注解,可以用JBEANBOX.ctx().setAllowSpringJsrAnnotation(false)去禁用JSR、Spring注解,这里ctx()方法返回的是默认bean容器,jBeanBox支持多个bean容器空间,每个容器可以有自已的设定。
jBeanBox也可以用JBEANBOX.ctx().setAllowAnnotation(false)去禁用包括自带注解在内的所有注解,也就是说只能用Java方式配置了。

关于@INJECT注解,jBeanBox与其它IOC工具不同点在于,它可以直接在@INJECT注解里指明目标类或配置类,如:
@INJECT(jdbcUrlBox.class) private String url; //其中jdbcUrlBox.class是一个BeanBox类,它的返回结果是由jdbcUrlBox这个配置类来决定的。这种方式的优点是支持重构和IDE快速定位到配置类。

jBeanBox对于静态定义的类,如果没有任何注解定义,默认均为单例类,所以每次ctx.getBean(SomeClass.class)都会获得同一个单例对象。

jBeanBox不建议在项目中使用@Named或@Qualifier,它们的主要问题是不支持IDE定位,如ctx.getBean("jdbcURL")无法利用IDE快速定位到配置文件,不利于维护。jBeanBox新增这两个注解的支持主要是考虑兼容性。

jBeanBox支持类似Guice中的绑定语法,可以用ctx.bind("xxId",box)方法手工给目标类或配置类绑定一个ID值,然后用getBean("xxId")来获取它。绑定是链式的,键可以是任意对象类型,键本身也可以作为目标,形成一个链式查找。

jBeanBox默认不进行类的自动扫描,所以启动非常快速。如果需要对包进行类扫描,把所有@COMPONENT注解标记的类登记到容器里,必须手工调用ctx.scanComponents("包名1","包名2"...)来进行扫描。手工扫描只是进行配置的登记,并不创建Bean的实例,也就是说jBeanBox的所有Bean都是懒初始化的,直到碰到getBean方法或@INJECT注入时,才会开始创建Bean的实例。如果需要在程序启动时初始化单例类,必须手工调用一次getBean()方法,从而生成单例实例并缓存在bean容器里。

因为注解注入方式大家比较熟悉,与Spring/Guice/JSR标准中的命名和用法类似,这里就不作详细介绍了,在jBeanBox\test目录下能找到各种使用演示,如:

AnnotationInjectTest.java 演示各种注解注入方式
JavaInjectTest.java 演示各种Java注入方式配置
QualiferTest.java 演示@Named、@Qualifer注解使用,注意这里还有手工进行类扫描的示例

jBeanBox的Java方式配置

jBeanBox的Java方式配置非常强大灵活,以下先通过一个例子来演示10种不同的注入方式:

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= "User10";}
	}

	public static class UserBox extends BeanBox {
		Object create() {return new User("User2");}
	}
	
	public static class UserBox7 extends BeanBox {
		{   setBeanClass(User.class);
			setProperty("name", "User7");
		} 
	}

	public static class H8 extends UserBox {{setAsValue("User8");}}
 
	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"));
		User u7 = new UserBox7().getBean();
		
		BeanBoxContext ctx = new BeanBoxContext(); 
		Interceptor aop=new MethodInterceptor() { 
			public Object invoke(MethodInvocation invocation) throws Throwable { 
				invocation.getArguments()[0]="User9";
				return invocation.proceed();
			}
		};
		User u8 = ctx.rebind(String.class, "8").bind("8", H8.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
		System.out.println(u8.name); //Result: User8
		u8.setName("");
		System.out.println(u8.name); //Result: User9
		ctx.close();
		System.out.println(u8.name); //Result: User10 
	}
}

这个例子的输出结果是依次打印出“User1” 、“User2”...到“User10”。下面遂一解释:

  1. 第一个利用了@VALUE("User1")注解,进行了构造器注入。
  2. 第二个利用一个jBeanBox的纯Java配置类UserBox,这是一个纯粹的Java类(不象Spring中的Java配置类是一个特殊的类,它在运行期会产生一个代理类), 在这个示例里它的create方法手工生成了一个User("User2")对象。
  3. 第三个是动态生成一个BeanBox配置,动态配置它的构造器注入,注入值为"User3"。
  4. 第四个也是动态配置,演示了字段注入,注入值为常量"User4"。
  5. 第五个是方法注入的演示,注入参数依次为:方法名、参数类型们、实际参数们。
  6. 第六个是setPostConstruct注入,等效于@PostConstruct注解,即Bean生成后立即执行的方法为init()方法。
  7. 第七个UserBox7是一个普通的BeanBox配置类,它设定了Bean类型,这种方式将调用它的无参构造器生成实例,然后注入它的name属性为"User7"。
  8. 第八个比较复杂,ctx是一个新的上下文实例,它先获取User.class的固定配置,然后给它的setName方法添加一个AOP切面,然后注入"name"字段为autowired类型,也就是说String类型,不过在此之前String类被绑定到字符串"8",字符串"8"又绑定到H8.class,H8又继承于UserBox,UserBox又返回"User2",然而都是浮云,因为H8本身被配置成一个值类型"User8",于是最后输出结果是“User8”。
  9. 第九个比较简单,因为setName方法被添加了一个AOP拦截器,参数被改成了"User9"。
    10.第十个是因为ctx这个上下文结束,所有单例被@PreDestroy标注的方法会执行。

上例除了一头一尾外,主要演示了jBeanBox的Java方法配置,Java方法即可以动态执行,也可以在定义好的BeanBox类中作为固定配置执行,固定的配置可以打下配置的基调,当固定配置需要变动时可以用同样的Java方法来进行调整(因为本来就是同一个BeanBox对象)甚至临时创建出新的配置,所以jBeanBox同时具有了固定配置和动态配置的优点。另外当没有源码时,例如配置第三方库的实例,这时所有的注解方式配置都用不上,唯一能用的只有Java配置方式。

上例中的value()方法是从JBEANBOX类中静态引入的全局方法,这个示例的源码位于单元测试目录下的HelloWorld.java。

jBeanBox特有的Java配置方式可以写出非常清晰易读的配置类来,例如下面这些配置层层继承:

	public static class HikariCPBox extends BeanBox { 
		public HikariDataSource create() {
			HikariDataSource ds = new HikariDataSource();
			ds.addDataSourceProperty("cachePrepStmts", true);
			ds.addDataSourceProperty("prepStmtCacheSize", 250); 
			ds.setMaximumPoolSize(3);
			ds.setConnectionTimeout(5000);
			this.setPreDestroy("close");// jBeanBox will close pool
			return ds;
		}
	}

	public static class MySqlDataSourceBox extends HikariCPBox {
		{
			injectValue("jdbcUrl", "jdbc:mysql://127.0.0.1:3306/test?rewriteBatchedStatements=true&useSSL=false");
			injectValue("driverClassName", "com.mysql.jdbc.Driver");
			injectValue("username", "root");
			injectValue("password", "password");
		}
	}

	public static class OracleDataSourceBox extends MySqlDataSourceBox {//继承父类的username和password
		{
			injectValue("jdbcUrl", "jdbc:oracle:thin:@127.0.0.1:1521:XE");
			injectValue("driverClassName", "oracle.jdbc.OracleDriver"); 
		}
	}

       public static class DataSourceBox extends OracleDataSourceBox {
	}

最后在程序的任意地方调用JBEANBOX.getBean(DataSourceBox.class)就可以获取一个数据源,数据源的类型由配置文件来决定。和Spring利用方法进行的Java配置不同,jBeanBox的配置是利用Java类本身,所以配置可以写在任意地方,不需要加任何注解,因为配置就是普通Java类。

jBeanBox的Java方式配置详解

以上只是笼统演示了一下jBeanBox的Java方式配置,以下是它的Java配置方法详解:

  • setAsValue(Object) 将当前BeanBox配置成一个常量值,等同于setTarget(Obj)+setPureVale(true)
  • setPrototype(boolean) 如参数为true时表示它是一个非单例,与setSingleton方法正好相反
  • injectConstruct(Class<?>, Object...) 设定构造器注入,参数分别是类、构造器参数类型们、参数们
  • injectMethod(String, Object...) 设定某个方法注入,参数分别是方法名、参数类型们、参数们
  • addMethodAop(Object, Method) 对某个方法添加AOP,参数分别是AOP类或实例、方法
  • addMethodAop(Object, String, Class<?>...) 对某个方法添加AOP,参数分别是AOP类或实例、方法名、参数类型们
  • addBeanAop(Object, String) 对整个Bean添加AOP,参数分别是AOP类或实例、方法规则(如"setUser*"),
  • setPostConstruct(String) 设定一个PostConstruct方法名,效果等同与@PostConstruct注解
  • setPreDestroy(String) 设定一个PreDestroy方法名,效果等同与@PreDestroy注解
  • injectField(String, BeanBox) 注入一个字段,参数是字段名、BeanBox实例,它的等效注解是@INJECT
  • setProperty(String, Object) 等同于injectValue方法
  • injectValue(String, Object) 注入一个字段,参数是字段名、对象实例,可与它类比的注解是@VALUE
  • setTarget(Object) 注定当前Bean的目标,另外当bind("7",User.class)时,setTarget("7")就等同于setTarget(User.class)
  • setPureValue(boolean) 表示target不再是目标了,而是作为纯值返回,上行的"7"就会返回字符串"7"
  • setBeanClass(Class<?>) 设定当前BeanBox的最终目标类,所有的配置都是基于这个类展开
  • setSingleton(Boolean) 如参数为true时表示它是一个单例,与setPrototype方法正好相反
  • setConstructor(Constructor<?>) 设定一个构造器
  • setConstructorParams(BeanBox[]) 设定构造器的参数,与上行联用
  • setPostConstruct(Method) 设定一个PostConstruct方法,效果等同与@PostConstruct注解
  • setPreDestroy(Method) 设定一个PreDestroy方法名,效果等同与@PreDestroy注解

Java方式配置,对于BeanBox来说,还有两个特殊的方法create和config,如下示例:

public static class DemoBox extends BeanBox {

		public Object create() {
			return new Book();
		}

		public void config(Object o) {
			(Book)o.setTitle("Foo");
		}
	}

上例表示DemoBox中创建的Bean是由create方法来生成,由config方法来修改。
另外提一下,create方法和config方法可以带BeanBoxContext参数,用在比较特殊的需要使用上下文的场合。

jBeanBox的AOP(面向切面编程)

jBeanBox功能大都可以用Java配置或注解配置两种方式来实现,同样地,它对AOP的支持也有两种方式:

Java方式AOP配置

  • someBeanBox.addMethodAop(Object, String, Class<?>...) 对某个方法添加AOP,参数分别是AOP类或实例、方法名、参数类型们。
  • someBeanBox.addBeanAop(Object, String) 对整个Bean添加AOP,参数分别是AOP类或实例、方法规则(如"setUser*|getName*")。
  • someBeanBoxContext.addContextAop(Object, Object, String);对整个上下文添加AOP规则,参数分别是AOP类或实例、类或类名规则、方法名规则。
    以上三个方法分别对应三种不同级别的AOP规则,第一个方法只针对方法,第二个方法针对整个类,第三个方法针对整个上下文。以下是一个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 ContextAOP 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.ctx().addContextAop(ContextAOP.class, 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);
	}

jBeanBox中的命名匹配规则采用星号做为模糊匹配字符,代表任意长度、任意字符,但一个规则里只允许出现一个星号,多个规则之间用"|"号分隔。

注解方式AOP配置

注解方式AOP只有两种类型,针对方法的和针对类的,没有针对上下文的。注解方式配置使用方便,但前提是必须要有源码存在。 注解方式需要用到一个特殊的注解@AOP,它是用来自定义自已的AOP注解用的,使用示例如下:

public static class Interceptor1 implements MethodInterceptor {//标准AOP联盟接口
		public Object invoke(MethodInvocation invocation) throws Throwable {
			invocation.getArguments()[0] = "1";
			return invocation.proceed();
		}
	}

	public static class Interceptor2 implements MethodInterceptor {//标准AOP联盟接口
		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("--");//切面生效,把参数改成“1”
		Assert.assertEquals("1", demo.name); 
		demo.setAddress("--");//切面生效,把参数改成“2”
		Assert.assertEquals("2", demo.address);
	}

本文所说的AOP是针对Aop alliance联盟标准的接口来说的,它已经被包含在jBeanBox中,无需再单独引入(当然重复引入也不会有问题)。Aop alliance联盟标准是比较有用的一个接口,实现了各种AOP实现之间的互换性,基于它,jBeanBox可以替换掉Spring的内核而使用它的声明式事务,这种互换性能够实现的前提就是因为Spring的声明式事务实现(如TransactionInterceptor)也实现了Aop alliance联盟标准接口MethodInterceptor。

jBeanBox的最新版本,AOP功能大幅削减,去掉了不常用的前置、后置、异常切面功能,只保留了支持AOP alliance联盟标准接口MethodInterceptor(注意在CGLIB中有一个同名的接口,不要混淆)。实现了MethodInterceptor接口的类,通常称为Interceptor,但在jBeanBox中图省事,也把它称为AOP,毕竟写成addBeanAop要比写成addBeanInterceptor简洁一些。

关于循环依赖

jBeanBox具备循环依赖检测功能,如果发现循环依赖注入(如A构造器中注入B,B的构造器中又需要注入A),将会抛出BeanBoxException运行时异常。 但是,以下这种字段或方法中出现的循环依赖注入在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支持多个上下文实例(BeanBoxContext),上下文也可以称为Bean容器。每个上下文实例都是互不干拢的。例如一个User.class可以在3个上下文中各自用不同的配置方式(注解、Java)生成3个“单例”,这3个“单例”都是相对于当前上下文唯一的,它们的属性与各自的配置有关。

JBEANBOX.getBean()方法是利用了一个缺省的全局上下文,可以用JBEANBOX.ctx()方法来获取这个全局上下文,所以如果一个项目中不需要用到多个上下文,可以直接使用JBEANBOX.getBean()方法,这样更方便。
JBEANBOX不是jBeanBox项目的关键类,它只是提供了一组静态全局方法供调用,以操纵默认的缺省全局上下文。

BeanBoxContext的每个实例都在内部维护着配置信息、单例缓存等,在BeanBoxContext实例的close方法被调用后,它的配置信息和单例被清空,当然,在清空之前,所有单例类的PreDestroy方法(如果有的话)被调用运行。所以对于需要回调PreDestroy方法的上下文来说,在关闭时不要忘了手工调用reset方法(或close方法)进行收尾清理。

BeanBoxContext的常用方法详解:

  • reset() 这个静态方法重置所有静态全局配置,并调用缺省上下文实例的close方法。
  • close() 先调用当前上下文缓存中单例实例的PreDestroy方法(如果有的话),然后清空当前上下文的缓存。
  • getBean(Object) 根据目标对象(可以是任意对象类型),返回一个Bean,如果找不到则抛出异常
  • getInstance(Class) 根据目标类T,返回一个T类型的实例, 如果找不到则抛出异常
  • getBean(Object, boolean) 根据目标对象,返回一个Bean, 第二个参数为false时如果找不到则返回Empty.class
  • getInstance(Class, boolean) 根据目标类T,返回一个T类型的实例, 第二个参数为false时如果找不到则返回Empty.class
  • bind(Object, Object) 给目标类绑定一个ID,例如:ctx.bind("A","B").bind("B".C.class),则以后可以用getBean("A")获取C的实例
  • addGlobalAop(Object, String, String) 在当前上下文环境添加一个AOP(详见AOP一节),第二个参数为类名模糊匹配规则,如"com.tom.*"或"*.tom"等,*号只允许出现一次, 第三个参数为方法名模糊匹配规则,如"setUser*"或"*user"等。
  • addGlobalAop(Object, Class<?>, String) 在当前上下文环境添加一个AOP,第二个参数为指定类(会匹配所有与指定类名称开头相同的类,例如指定类为a.b.C.class, 则a.b.CXX.class也会被匹配),第三个参数为方法名模糊匹配规则。
  • getBeanBox(Class<?>) 获取一个类的BeanBox实例,例如一个注解标注的类,可以用这个方法获取BeanBox实例,然后再添加、修改它的配置,这就是固定配置和动态配置的结合运用。
  • setAllowAnnotation(boolean) 设定是否允许读取类中的注解,如果设为flase的话,则jBeanBox只允行使用纯Java配置方式。默认true。
  • setAllowSpringJsrAnnotation(boolean) 设定是否允先读取类中JSR330/JSR250和Spring的部分注解,以实现兼容性。默认true。
  • setValueTranslator(ValueTranslator) 设定对于@VALUE注解中的字符串参数如何解析它,例如@VALUE("#user"),系统默认返回"#user"字符串,如果需要不同的解析,例如读取属性文本中的值,则需要自已设定一个实现了ValueTranslator接口的实例。

jBeanBox的性能

以下为jBeanBox的性能与其它IOC工具的对比,只对比DI注入功能,搭建一个由6个对象组成的实例树,可见jBeanBox创建非单例的速度比Guic慢一倍、比Spring快45倍左右。一般来说,IOC工具多应用在单例场合,因为从缓存中取,性能大家都差不多,所以性能不是关键。但是如果遇到个别需要频繁生成非单例的场合,例如每次访问生成一个新的页面对象实例,这时Spring就有可能成为性能瓶颈。

测试程序详见:[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

以上就是对jBeanBox的介绍,没有别的文档了,因为毕竟它的核心源码也只有3000行(第三方工具如CGLIB、JSR的源码不算在内),我怕再写下去,使用说明会超过它的源码行数,有问题去看看它的源码或单元测试可能更简单一点。

更多关于jBeanBox的用法还可以在jSqlBox项目中看到它的运用(数据源的配置、声明式事务示例等)。

Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

简介

jBeanBox是一个微形但功能较齐全的IOC/AOP工具 展开 收起
Java
Apache-2.0
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
Java
1
https://gitee.com/ackvip/jBeanBox.git
git@gitee.com:ackvip/jBeanBox.git
ackvip
jBeanBox
jBeanBox
master

搜索帮助

14c37bed 8189591 565d56ea 8189591