|
| 1 | +#title: 工厂方法 |
| 2 | +#author:wendal(wendal1985@gmail.com) |
| 3 | +#index:0,1 |
| 4 | +-------------------------------------------------------------------------------------------------------- |
| 5 | +什么是工厂方法? |
| 6 | + |
| 7 | + 工厂方法,就是通过一个"虚拟"构造方法,供调用者获取特定的实例. 至于返回的是什么实例, 得看环境和传入的参数,及 |
| 8 | + 方法内的业务逻辑了. |
| 9 | + |
| 10 | + 例如, 希望在生产环境用Product目录下的配置文件,开发环境用dev目录下的配置文件 |
| 11 | + |
| 12 | +-------------------------------------------------------------------------------------------------------- |
| 13 | +使用Iocbean的factory |
| 14 | + |
| 15 | + 通过IocBean注解内的factory参数,可以自定义工厂类及工厂method |
| 16 | + |
| 17 | + factory参数的规则是, 以井号分隔,井号之前的是类名或ioc bean名称, 后面是方法名称. |
| 18 | + |
| 19 | + {{{<Java> |
| 20 | + @IocBean(factory="net.wendal.mqtt.MqttAbcServiceFactory#create", args={"refer:dao"}) |
| 21 | + public class AbcService extends Service { |
| 22 | + ... |
| 23 | + |
| 24 | + } |
| 25 | + |
| 26 | + // 无任何注解 |
| 27 | + public class MqttAbcServiceFactory { |
| 28 | + public static AbcService create(Dao dao) { |
| 29 | + return new XXXXAbcService(dao); |
| 30 | + } |
| 31 | + } |
| 32 | + }}} |
| 33 | + |
| 34 | + 通过其他bean生成此bean, 区别就是用`$对象名称` 代替 上一个例子的类名 |
| 35 | + |
| 36 | + {{{<Java> |
| 37 | + @IocBean(factory="$snakerConfigure#build") |
| 38 | + public class SnakerService{} |
| 39 | + |
| 40 | + |
| 41 | + @IocBean(name="snakerConfigure") |
| 42 | + public class SnakerConfigure { |
| 43 | + public SnakerService build() { |
| 44 | + return ....; |
| 45 | + } |
| 46 | + } |
| 47 | + }}} |
| 48 | + |
| 49 | +-------------------------------------------------------------------------------------------------------- |
| 50 | +使用IocBean实例方法 |
| 51 | + |
| 52 | + 先看示例. 这个功能是1.r.62新增. |
| 53 | + |
| 54 | + 相比@IocBean的factory参数, 这种方式是声明"其他"bean的生成, 而不是自身. |
| 55 | + |
| 56 | + {{{<JAVA> |
| 57 | +@IocBean // 首先,它自己必须加@IocBean, 可以使用@IocBean/@Inject的全部功能. |
| 58 | +public class MyBeanFactory { |
| 59 | + |
| 60 | + //@Inject |
| 61 | + //public PropertiesProxy conf; // 像普通对象那么注入任何你需要的东西,这个conf也可是其他IocBean类,但不能是这个类了,否则死循环了 |
| 62 | + @IocBean |
| 63 | + public PropertiesProxy getConf() { |
| 64 | + if ("product".equals(System.getProperty("nutz.runmode"))) { |
| 65 | + return new PropertiesProxy("/etc/nutz/custom"); |
| 66 | + } else { |
| 67 | + return new PropertiesProxy("custom/"); |
| 68 | + } |
| 69 | + } |
| 70 | + |
| 71 | + // 生成一个名为dataSource的bean. 命名规则是: IocBean(name=XXX) > 方法名去掉get/build后首字母小写. |
| 72 | + @IocBean |
| 73 | + public SimpleDataSource getDataSource(PropertiesProxy conf) { |
| 74 | + SimpleDataSource ds = new SimpleDataSource(); |
| 75 | + ds.setJdbcUrl(conf.get("db.url", "jdbc:h2:mem:nutztest")); |
| 76 | + return ds; |
| 77 | + } |
| 78 | + |
| 79 | + @IocBean |
| 80 | + public Dao buildDao(DataSource dataSource) { // 带参数, 默认是按类型注入 |
| 81 | + return new NutDao(dataSource); |
| 82 | + } |
| 83 | + |
| 84 | + |
| 85 | + @IocBean(name="dao2") // 自定义bean的名字,这样方法名就随便起了 |
| 86 | + public Dao xxxgetDao2(DataSource dataSource) { |
| 87 | + return new NutDao(dataSource); |
| 88 | + } |
| 89 | + |
| 90 | + |
| 91 | + @IocBean(name="dao3") |
| 92 | + public Dao xxyyy(@Inject("refer:dataSource")DataSource ds) { // 参数加@Inject,可以像属性加上@Inject一样注入值 |
| 93 | + return new NutDao(ds); |
| 94 | + } |
| 95 | + |
| 96 | + @IocBean(name="dao3", create="init", depose="depose") // 事件也是支持的 |
| 97 | + public UserService makeUserService(Dao dao) { |
| 98 | + return new UserServiceImpl(dao); |
| 99 | + } |
| 100 | +} |
| 101 | + }}} |
| 102 | + |
| 103 | + 优缺点 |
| 104 | + |
| 105 | + * 可以完全不使用js进行ioc配置 |
| 106 | + * 可以更灵活地根据配置信息生成对象 |
| 107 | + * 通过这种方式生成的对象,暂不支持Aop注入 |
0 commit comments