写在前面的话

适用读者:有一定经验的,本文不适合初学者,因为可能不能理解我在说什么

文章思路:不会一开始就像别的博客文章那样,Bean 的生命周期,源码解读(给你贴一大堆的源码)。个人觉得应该由问题驱动,为什么为出现 BeanFactory ,为什么会有生命周期。

正文

一开始我们使用 bean 都是简单bean,如 vo ,po,entity,dto,我们是这么玩的

XXEntity xxEntity = new XXEntity(); xxEntity.setPropA("字符串");

后面可能出现了某个比较复杂的 bean ,它有一个对象做为属性,需要在构造时或构造后设置值(示例而已,不要较真),如

// 构建序列化实例,这里 Serializable 是接口,使用接口的好处是在使用别的序列化时,不需要修改 jedis 类 Serializable fastJsonSerizlizable = new FastJsonSerizlizable();  // 构建目标 jedis 实例 ,需要先构建序列化对象  Jedis jedis = new Jedis(); jedis.setSerializable(fastJsonSerizlizable);

这时来了 serviceA 类和 serviceB 类,它们都需要使用 redis,我不可能在每个类里面都去把 jedis 实例化的过程写一遍,这时有经验的同学会写一个工具类来创建 jedis ,像这样

public BeanUtil {     // 可以把创建序列化单拿出来,因为除了 redis 需要序列化之外,kafka 也需要序列化     public static Serializable createSerializable(){         return new FastJsonSerizlizable();     }          public static Jedis createJedis(){         Jedis jedis = new Jedis();         jedis.setSerializable(createSerializable());         return jedis;     } }  // 这里我 serviceA,serviceB 都可以使用 createJedis 来直接获取 jedis 实例 ,而不需要关心创建细节,使用哪个序列化等问题

上面代码有几个问题

  • 每次使用时都会创建 jedis 对象 ,而每一个 jedis 对象又会单独对一个 Serializable 对象 ,但是 fastJson 的序列化和 jedis 都只是工具类型的东西,一个实例足已。
  • 无法对 Jedis 进行配置
  • 不能让使用者去创建 BeanUtil 实例 ,改进的代码 如下
public BeanUtil {     // 禁用 BeanUtil 构建      private BeanUtil(){}          // 这里我们可以使用 bean 的全路径 => bean 实例来缓存 bean      static Map<String,Object> beansCache = new ConcurrentHashMap<String,Object>();          static{         // 初始化时,在内容缓存这些 bean 的实例,因为 jedis 依赖于 serializable ,需要需要先创建 serializable         Serializable serializable = createSerializable();         beansCache.put(Serializable.class.getSimpleName(),serializable);         Jedis jedis = createJedis();         beansCache.put(jedis.class.getSimpleName(),jedis);     }          static Serializable createSerializable(String type){         Serializable serializable =  beansCache.get("serializable");         if(serializable != null)return serializable;                  switch(type){             case "kryo":    // kryo 不能用单例,请忽略本问题,示例而已                 return new KryoSerializable();             case "protostuff":                 return new protostuffSerializable();             default:                 return new FastJsonSerizlizable();         }     }          static Jedis createJedis(String serializableType){         Jedis jedis = new Jedis();         Serializable serializable = beansCache.get("serializable");         jedis.setSerializable(serializable);         return jedis;     }      //然后对外提供获取 Bean 的方法      public static Object getBean(String beanName){         return beansCache.get(beanName);     }          public static T getBean(Class<T> type){         return beansCache.get(type.getSimpleName());     }  }

但如果写这个类的是小明,经过一段时间后这个类里会出现大量的 createXx 和 XX 的初始化操作,而且依赖程度也非常复杂,这时小明想,是时候优化一波了,于是小明想了一种解决方案,定义了一种 xml 语法

使用 bean 标签来定义一个 bean,每个 bean 都有唯一的一个 id 信息 ,使用 property 来定义它的属性 ,如果是复杂属性使用 ref ,解析这个xml 得到一个完整的 bean 依赖图

<beans>     <bean id="serializable" class="com.xx.FastJsonSerizlizable" />          <bean id="jedis" class="com.xx.Jedis">         <property name="host" value="localhost" />         <property name="serializable"