Java 中 HashMap/ List初始化时赋值

1、HashMap 初始化的文艺写法

HashMap 是一种常用的数据结构,一般用来做数据字典或者 Hash 查找的容器。普通青年一般会这么初始化:
HashMap<String, String> map = new HashMap<String, String>();
map.put("name", "test");  
map.put("age", "20");


看完这段代码,很多人都会觉得这么写太啰嗦了,文艺青年一般这么来了:
HashMap<String, String> map = new HashMap<String, String>() {
    {
        put("name", "test");  
        put("age", "20"); 
    }
};


看起来优雅了不少,一步到位,一气呵成的赶脚。然后问题来了,这里的双括号”{{}}”到底什么意思,什么用法呢?
双括号”{{}}”,用来初始化,使代码简洁易读。
第一层括弧实际是定义了一个匿名内部类 (Anonymous Inner Class),第二层括弧实际上是一个实例初始化块 (instance initializer block),这个块在内部匿名类构造时被执行。


2、推而广之,可初始化ArrayList、Set


List<String> names = new ArrayList<String>() {
    {
        for (int i = 0; i < 10; i++) {
            add("A" + i);
        }
    }
};
System.out.println(names.toString());


3、Java7:增加对collections的支持
在 Java 7 中你可以像 Ruby, Perl、Python 一样创建collections了, 但是这些集合是不可变的。


List<String> list = ["item"];
String item = list[0];
  
Set<String> set = {"item"};
  
Map<String, Integer> map = {"key" : 1};
int value = map["key"];


4、文艺写法的潜在问题


文章开头提到的文艺写法的好处很明显就是一目了然。这里来罗列下此种方法的坏处,如果这个对象要串行化,可能会导致串行化失败。
1.此种方式是匿名内部类的声明方式,所以引用中持有着外部类的引用。所以当时串行化这个集合时外部类也会被不知不觉的串行化,当外部类没有实现serialize接口时,就会报错。
2.上例中,其实是声明了一个继承自HashMap的子类。然而有些串行化方法,例如要通过Gson串行化为json,或者要串行化为xml时,类库中提供的方式,是无法串行化Hashset或者HashMap的子类的,从而导致串行化失败。解决办法:重新初始化为一个HashMap对象:


new HashMap(map);
这样就可以正常初始化了。


5、执行效率问题


当一种新的工具或者写法出现时,猿们都会来一句:性能怎么样?(这和男生谈论妹纸第一句一般都是:“长得咋样?三围多少?”一个道理:))
关于这个两种写法我这边笔记本上测试文艺写法、普通写法分别创建 10,000,000 个 Map 的结果是 1217、1064,相差 13%。
public class Test {
    public static void main(String[] args) {
        long st = System.currentTimeMillis();
        /*
        for (int i = 0; i < 10000000; i++) {
            HashMap<String, String> map = new HashMap<String, String>() {
                {
                    put("name", "test");
                    put("age", "20");
                }
            };
        }
        System.out.println(System.currentTimeMillis() - st); // 1217
        */


        for (int i = 0; i < 10000000; i++) {
            HashMap<String, String> map = new HashMap<String, String>();
            put("name", "test");
            put("age", "20");
        }
        System.out.println(System.currentTimeMillis() - st); // 1064
    }
}

 

转自:https://www.cnblogs.com/pejsidney/p/9235343.html

<think>好的,我现在要帮助用户理解Spring中Bean的创建、初始化赋值的源码流程。用户之前已经询问过关于构造器注入List的内容,现在他想更深入地了解Bean的生命周期中的这些阶段。我需要回忆一下Spring的源码结构,尤其是BeanFactory和相关的处理器。 首先,用户可能想知道Bean的整个创建过程,从实例化到初始化,再到属性赋值的步骤。我需要分步骤解释,每个阶段的关键类和方法的源码位置。比如Bean的创建可能在AbstractAutowireCapableBeanFactory的createBean方法中,初始化可能会涉及到InitializingBean接口和init-method。 然后,我需要考虑用户可能的疑惑点,比如BeanPostProcessor的作用,属性注入的具体过程,以及循环依赖的处理。在源码解析,要指出关键方法,比如doCreateBean、populateBean、initializeBean等。 另外,用户之前的问题是关于构造器注入,这次可能想了解更广泛的属性赋值方式,比如setter注入或字段注入。需要确保覆盖到不同的注入方式在源码中的处理。 还要注意用户对性能优化和特殊场景处理的兴趣,比如延迟加载或循环依赖的问题,可能需要提到三级缓存机制。 最后,要确保回答结构清晰,步骤分明,结合代码示例和源码片段,帮助用户逐步理解。可能需要用中文注释解释关键代码,并指出源码的位置,方便用户进一步查阅。</think>以下是Spring框架中Bean创建、初始化赋值的核心源码解析(基于Spring 5.3.x版本): --- ### 一、整体流程概览 ```plantuml @startuml start -> 实例化(createBeanInstance) -> 属性赋值(populateBean) -> 初始化(initializeBean) -> 注册销毁方法(registerDisposableBean) -> end @enduml ``` --- ### 二、核心源码解析 #### 1. Bean创建入口 **源码位置**:`AbstractAutowireCapableBeanFactory#createBean` ```java protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { // 前置处理(类加载、方法覆盖验证) Class<?> resolvedClass = resolveBeanClass(mbd, beanName); // 实际创建方法 Object beanInstance = doCreateBean(beanName, mbd, args); return beanInstance; } ``` #### 2. 实例化阶段 **源码位置**:`AbstractAutowireCapableBeanFactory#doCreateBean` ```java protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { // 实例化(通过构造器/工厂方法) BeanWrapper instanceWrapper = createBeanInstance(beanName, mbd, args); // 提前暴露引用(解决循环依赖) if (earlySingletonExposure) { addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } // 属性赋值 populateBean(beanName, mbd, instanceWrapper); // 初始化 initializeBean(beanName, exposedObject, mbd); return exposedObject; } ``` --- ### 三、初始化阶段详解 #### 1. 初始化方法调用顺序 ```java protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) { // 1. Aware接口注入 invokeAwareMethods(beanName, bean); // 2. BeanPostProcessor前置处理 wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean, beanName); // 3. 自定义初始化方法 invokeInitMethods(beanName, wrappedBean, mbd); // 4. BeanPostProcessor后置处理 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); return wrappedBean; } ``` #### 2. 关键方法源码 **(1)属性注入** 源码位置:`AbstractAutowireCapableBeanFactory#populateBean` ```java protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { // 执行InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation() if (!continueWithPropertyPopulation) return; // 自动装配处理(byName/byType) if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) { autowireByName(beanName, mbd, bw, newPvs); autowireByType(beanName, mbd, bw, newPvs); } // 处理@Autowired/@Value等注解 for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; pvs = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); } } // 应用属性值 applyPropertyValues(beanName, mbd, bw, pvs); } ``` **(2)初始化方法** 源码位置:`AbstractAutowireCapableBeanFactory#invokeInitMethods` ```java protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd) throws Throwable { // 1. 执行InitializingBean接口 if (bean instanceof InitializingBean) { ((InitializingBean) bean).afterPropertiesSet(); } // 2. 执行自定义init方法 String initMethodName = mbd.getInitMethodName(); if (StringUtils.hasLength(initMethodName)) { Method initMethod = ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName); initMethod.invoke(bean); } } ``` --- ### 四、核心扩展点 #### 1. BeanPostProcessor处理链 ```java // 前置处理 public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) { Object result = existingBean; for (BeanPostProcessor processor : getBeanPostProcessors()) { Object current = processor.postProcessBeforeInitialization(result, beanName); if (current == null) return result; result = current; } return result; } // 后置处理(包含AOP代理生成) public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) { Object result = existingBean; for (BeanPostProcessor processor : getBeanPostProcessors()) { Object current = processor.postProcessAfterInitialization(result, beanName); if (current == null) return result; result = current; } return result; } ``` #### 2. 循环依赖处理 **三级缓存实现**: ```java // DefaultSingletonBeanRegistry public class DefaultSingletonBeanRegistry ... { // 一级缓存(完整Bean) private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); // 二级缓存(早期引用) private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16); // 三级缓存(ObjectFactory) private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); } ``` --- ### 五、性能优化技巧 1. **延迟初始化**:使用`@Lazy`注解或设置`lazy-init="true"` 2. **作用域控制**:合理使用prototype和request作用域 3. **BeanPostProcessor优化**:避免在自定义Processor中进行复杂操作 4. **缓存配置**:使用`@Cacheable`减少重复计算 ```mermaid graph TD A[BeanDefinition加载] --> B[实例化] B --> C[属性赋值] C --> D[初始化] D --> E[使用] E --> F[销毁] ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值