工厂方法,就是通过一个"虚拟"构造方法,供调用者获取特定的实例. 至于返回的是什么实例, 得看环境和传入的参数,及方法内的业务逻辑了.
例如, 希望在生产环境用Product目录下的配置文件,开发环境用dev目录下的配置文件
通过IocBean注解内的factory参数,可以自定义工厂类及工厂method
factory参数的规则是, 以井号分隔,井号之前的是类名或ioc bean名称, 后面是方法名称.
@IocBean(factory="net.wendal.mqtt.MqttAbcServiceFactory#create", args={"refer:dao"}) public class AbcService extends Service { ... } // 无任何注解 public class MqttAbcServiceFactory { public static AbcService create(Dao dao) { return new XXXXAbcService(dao); } }
通过其他bean生成此bean, 区别就是用$对象名称 代替 上一个例子的类名
@IocBean(factory="$snakerConfigure#build")
public class SnakerService{}
@IocBean(name="snakerConfigure")
public class SnakerConfigure {
public SnakerService build() {
return ....;
}
}
先看示例. 这个功能是1.r.62新增.
相比@IocBean的factory参数, 这种方式是声明"其他"bean的生成, 而不是自身.
@IocBean // 首先,它自己必须加@IocBean, 可以使用@IocBean/@Inject的全部功能. public class MyBeanFactory { //@Inject //public PropertiesProxy conf; // 像普通对象那么注入任何你需要的东西,这个conf也可是其他IocBean类,但不能是这个类了,否则死循环了 @IocBean public PropertiesProxy getConf() { if ("product".equals(System.getProperty("nutz.runmode"))) { return new PropertiesProxy("/etc/nutz/custom"); } else { return new PropertiesProxy("custom/"); } } // 生成一个名为dataSource的bean. 命名规则是: IocBean(name=XXX) > 方法名去掉get/build后首字母小写. @IocBean public SimpleDataSource getDataSource(PropertiesProxy conf) { SimpleDataSource ds = new SimpleDataSource(); ds.setJdbcUrl(conf.get("db.url", "jdbc:h2:mem:nutztest")); return ds; } @IocBean public Dao buildDao(DataSource dataSource) { // 带参数, 默认是按类型注入 return new NutDao(dataSource); } @IocBean(name="dao2") // 自定义bean的名字,这样方法名就随便起了 public Dao xxxgetDao2(DataSource dataSource) { return new NutDao(dataSource); } @IocBean(name="dao3") public Dao xxyyy(@Inject("refer:dataSource")DataSource ds) { // 参数加@Inject,可以像属性加上@Inject一样注入值 return new NutDao(ds); } @IocBean(name="dao3", create="init", depose="depose") // 事件也是支持的 public UserService makeUserService(Dao dao) { return new UserServiceImpl(dao); } }
优缺点