林炳文Evankaka原创作品。转载请注明出处http://blog.csdn.net/evankaka

在定义了 JavaBean 装载信息之后需要对其赋值。一个 JavaBean 的赋值可以通过构造方法完成初始化,或者通过 set()方法初始化和改变属性值。下面分别介绍如何在 XML 中配置 JavaBean 的属性为构造方法和 set()方法传递参数。

本文工程下载

一、构造注入

在类被实例化的时候,它的构造方法被调用并且只能调用一次。所以它被用于类的初始化操作。<constructor-arg>是<bean>标签的子标签。通过其<value>子标签可以为构造
方法传递参数。现在以一个简单的输出学生信息的实例演示如何为构造方法传递参数。

实例程序创建过程如下。
(1)建立 Student 接口,它是对学生类的简单抽象。程序代码如下

package com.linbingwen;public interface Student {public void printInfo();
}

(2)建立实现 Student 接口的 Stu1 类,定义姓名、年龄、性别 3 个属性和包含这 3个参数的构造方法,在实现接口的 printInfo()方法中输出所有属性信息。程序代码如下

package com.linbingwen;public class Stu1 implements Student {private String name;private String sex;private int age;public Stu1(String name, String sex, int age) {super();this.name = name;this.sex = sex;this.age = age;}public void printInfo() {System.out.println("姓名:" + name);System.out.println("年龄:" + age);System.out.println("性别:" + sex);}
}

( 3 ) applicationContext.xml 是 装 配 JavaBean 的 配 置 文 件 , 它 通 过 3 个<constructor-arg>标签为构造方法传递两个 String 类型和一个 int 类型的参数。程序代
码如下。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd"><bean id="stu1" class="com.linbingwen.Stu1"><constructor-arg><value>飞龙</value></constructor-arg><constructor-arg><value>男</value></constructor-arg><constructor-arg><value>26</value></constructor-arg></bean>
</beans>

注意:这里要把applicationContext.xml放在src文件夹下。添加Spring和包不懂看这里
(4)创建 Info 类。它是实例的主类,负责载入容器,从容器中获得 Stu1 类的实例,并调用 Stu1 类的 pringInfo()方法打印学生信息。程序代码如下

package com.linbingwen;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class Info {public static void main(String[] args) {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");Student student = (Student) applicationContext.getBean("stu1");student.printInfo();}}

实例运行结果如图 所示。

通过这个实例,可以看到容器通过多个<constructor-arg>标签完成了对构造方法的传参,但是如果标签的赋值顺序与构造方法中参数的顺序或参数类型不同,程序会产生异常。<constructor-arg>标签可以使用“index”属性和“type”属性解决此类问题。下面分别介绍这两个属性的用法。
type 属性:可以指定参数类型以确定要为构造方法的哪个参数赋值。当需要赋值的属性在构造方法中没有相同的类型时,可以使用这个参数。因此实例中 stu1 的配置信息可以
这样写:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd"><bean id="stu1" class="com.linbingwen.Stu1"><constructor-arg><value>飞龙</value></constructor-arg><constructor-arg><value>男</value></constructor-arg><constructor-arg type="int"><value>26</value></constructor-arg></bean>
</beans>

index 属性:用于指定构造方法的参数索引,指定当前<constructor-arg>标签为构造方法的那个参数赋值。因为程序中含有两个 String 类型的参数,type 属性无法做判断,
导致 name 和 sex 参数无法判断正确性。这时需要设置 index 属性定义赋值索引来指定构造方法的参数位置。修改后的 applicationContext.xml 配置文件内容如下。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd"><bean id="stu1" class="com.linbingwen.Stu1"><constructor-arg index="0"><value>飞龙</value></constructor-arg><constructor-arg index="1"><value>男</value></constructor-arg><constructor-arg type="int"><value>26</value></constructor-arg></bean>
</beans>

在修改后的代码中,两个 String 类型的参数通过“index”属性指定了在构造方法中的位置,确保了传参的正确性,第 3 个<constructor-arg>标签的 type 属性可以改写成
“index=2”。现在的 3 个<constructor-arg>标签可以随意调换顺序而不会影响到构造方法的正确赋值。<constructor-arg>标签还有“ref”和“value”两个属性,分别用于引用其他 JavaBean和定义新值。由于使用构造方法在配置文件中定义 JavaBean 使用得不多,所以这两个属性不再介绍。

二、设值注入

一个简单的 JavaBean 最明显的规则就是以一个私有属性对应 set()和 get()方法,来实现对属性的封装。既然 JavaBean 有 set()方法来设置 Bean 的属性,Spring 就会有相应的支持。除了为构造方法传递参数的<constructor-arg>标签之外,<property>标签可以为JavaBean 的 set()方法传递参数,即通过 set()方法为属性赋值。在上面的实例中再添加一个 Moniter 类。

设置 Moniter 类属性和 set()/get()方法。程序代码如下。

package com.linbingwen;public class Moniter implements Student {private String name;private String sex;private int age;public void printInfo() {System.out.println("姓名:" + name);System.out.println("年龄:" + age);System.out.println("性别:" + sex);}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}
}

修改 applicationContext.xml 配置文件。添加名称为 Moniter 的 Java Bean 的定义,用<property>标签的“name”属性指定要操作的 JavaBean 的属性,然后通过<property>的子标签<value>为属性赋值。修改后的代码如下。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd"><bean id="stu1" class="com.linbingwen.Stu1"><constructor-arg index="0"><value>飞龙</value></constructor-arg><constructor-arg index="1"><value>男</value></constructor-arg><constructor-arg type="int"><value>26</value></constructor-arg></bean><bean id="moniter" class="com.linbingwen.Moniter"><property name="age"><value>26</value></property><property name="name"><value>欣欣</value></property><property name="sex"><value>女</value></property></bean>
</beans>

程序运行结果如图  所示

三、接口注入(interface injection)

接口注入指的就是在接口中定义要注入的信息,并通过接口完成注入。

具体步骤如下
①.编写一个接口IBuniness,各种数据库的注入将通过这个接口进行。代码如下

package ch3;public interface IBusiness {public void createDI(DataBase db);
}

②.任何想要使用数据库实例的类都必须实现这个接口,业务逻辑类Business实现这个接口IBusiness。代码如下

package ch3;public class Business implements IBusiness {private DataBase db;@Overridepublic void createDI(DataBase db) {//接口注入this.db = db;}
// 根据注入的数据库,从XXX数据库中取得数据。public void getData(){db.getData();}
}

3.编写测试类TestBusiness。代码如下

package ch3;
public class TestBusiness {private Business business = new Business();
// 根据注入的数据库类,从oracle中取得数据库。public void getData() {business.createDI(new OracleDataBase()); // 注入实际的数据库类型。如要变更式样,只需改变此处即可,达到重用目的。business.getData();}
}

如果要完成依赖关系注入的对象,必须实现IBusiness接口。

四、JavaBean 的赋值标签

以上只介绍了如何用<value>标签赋值,那么复杂的属性如何赋值呢?例如 Null、对象引用、集合类等。接下来将要介绍对 JavaBean 的复杂属性赋值的标签,它们可以应用到
任何如<constructor-arg>和<property>可以给 JavaBean 的属性赋值的标签中。
1.<value>标签
这是一个普通的赋值标签,可直接在成对的<value>标签中放入数值或其他赋值标签,Spring 会把这个标签提供的属性值注入到指定的 JavaBean 中。语法格式如下。

<value>arg</value>

arg:传递给 JavaBean 的属性值。
2.<ref>标签
这个标签可以引用其他 JavaBean 的实例对象,当传递的参数是其他 JavaBean 的实例对象时使用此标签。语法格式如下。

<ref bean="JavaBean"/>

bean:指定引用的 JavaBean。
3.<null>标签
这是为 JavaBean 赋 Null 空值的标签。当 JavaBean 的某个属性暂不使用,要将其设置为 Null 值时使用此标签。语法格式如下。

<null/>

<null></null>

4.<list>标签
这是为 List 集合类或数组赋值的标签。当 JavaBean 的某个属性是 List 集合类型或数组时,需要使用此标签为 List 集合类型或数组的每一个元素赋值。语法格式如下。

<list><value>arg1</value><value>arg2</value>
</list>

<value>:赋值标签,为<list>标签指定的属性赋值。也可以使用其他赋值标签作为集合类赋值标签的子标签,例如<ref>或 3.2.7 节中介绍的使用<bean>标签定义匿名内部
JavaBean 的方法。此标签应用在<bean>标签中定义 JavaBean 的完整代码举例如下。

<bean id="school" class="School"><property name="studentList"><list><ref bean=" student1"/><value>student2</value></list></property>
</bean>

5.<set>标签
和<list>标签类似,<set>标签也是为集合对象赋值,不过赋值的对象是 Set 类型的属性。语法格式如下。

<set><ref bean="arg1"/><value>arg2</value>
……
</set>

此标签应用在<bean>标签中定义 JavaBean 的完整代码举例如下

<bean id="school" class="School"><property name="student"><set><ref bean=" student1"/><value>name</value></set></property>
<bean>

6.<map>标签
此标签为 Map 集合赋值。因为 Map 以键值对(key/value)的方式存放数据,所以需要使用<entry>子标签装载 key 与 value 数据。Map 集合的 key 可以是任何类型的对象,而<entry>标签的属性 key 是以 String 类型表示的,所以限制了 Spring 中 Map 的 key 只能用 String 来表示。语法格式如下。

<map><entry key="key1"><ref bean="arg1" /></entry>
</map>

<entry>:<map>标签的子标签,其“key”属性用于指定 Map 集合类的键值(key)。此标签应用在<bean>标签中定义 JavaBean 的完整代码举例如下。

<bean id="school" class="School"><property name="student"><map><entry key="key1"><ref bean=" student1" /></entry><entry key="key2"><value> student2</value></entry></map>
</property>
</bean>

7.<props>标签
这是为 java.util.Properties 类型属性赋值的标签,和<map>标签类似,但是它的(key/value)键值全都是 String 类型的,无法赋予 Object 对象类型。语法格式如下。

<props>
<prop key="key1">value</prop>
</props>

<prop>:<props>的子标签,其“key”属性用于指定 Properties 类的键值(key)。此标签应用在<bean>标签中定义 JavaBean 的完整代码举例如下。

<bean id="school" class="School"><property name="student"><props><prop key="key1">student1</prop><prop key="key2">student2</prop></props></property>
</bean>

8 匿名内部 JavaBean 的创建
通过前面的介绍,读者应该对如何使用 XML 装配 JavaBean 有了一定的了解。但是编程中经常遇到匿名的内部类,在 Spring 中该如何利用 XML 装配呢?其实非常简单,在需要匿名内部类的地方直接用<bean>标签定义一个内部类即可。如果要使这个内部类匿名,可以不指定<bean>标签的 id 或 name 属性。例如下面这段代码:

<bean id="school" class="School"><property name="student"><bean class="Student"/> <!--定义学生匿名内部类--></property>
</bean>

代码中定义了匿名的 Student 类,将这个匿名内部类赋给了 school 类的实例对象。

五、 list、set、map注入使用范例

还是接上面的工程,新建一个School.java,代码如下:

package com.linbingwen;import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;public class School {private List listStu;private Set setStu;private Map mapStu;public List getListStu() {return listStu;}public void setListStu(List listStu) {this.listStu = listStu;}public Set getSetStu() {return setStu;}public void setSetStu(Set setStu) {this.setStu = setStu;}public Map getMapStu() {return mapStu;}public void setMapStu(Map mapStu) {this.mapStu = mapStu;}public void printSchool(){System.out.println("--------list--------");  for (int i = 0; i < listStu.size(); i++) {  System.out.println(listStu.get(i));  }    System.out.println("--------set--------");  for(Object s : setStu){  System.out.println(s);  }   System.out.println("--------map--------");  Iterator it=mapStu.entrySet().iterator();          System.out.println(mapStu.entrySet().size());    String key;          String value;   while(it.hasNext()){   Map.Entry entry = (Map.Entry)it.next();          key=entry.getKey().toString();          value=entry.getValue().toString();          System.out.println(key+"===="+value);                    }   }
}

applicationContext.xml如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd"><bean id="stu1" name="student1" class="com.linbingwen.Stu1"><constructor-arg index="0"><value>飞龙</value></constructor-arg><constructor-arg index="1"><value>男</value></constructor-arg><constructor-arg type="int"><value>26</value></constructor-arg></bean><bean id="moniter" name="student2" class="com.linbingwen.Moniter"><property name="age"><value>26</value></property><property name="name"><value>欣欣</value></property><property name="sex"><value>女</value></property></bean><bean id="school" class="com.linbingwen.School"><!--List 注入例子 --><property name="listStu"><list><ref bean="moniter" />  <!--使用上面已定义好的bean --><ref bean="moniter" />  <!--使用上面已定义好的bean --><ref bean="stu1" />     <!--使用上面已定义好的bean --><bean class="com.linbingwen.Moniter"> <!--定义学生匿名内部类,用setter方法注入 --><property name="age" value="20" /><property name="name" value="阿屁" /><property name="sex" value="男" /></bean><value>1</value><value>hello</value></list></property><!--set 注入例子 --><property name="setStu"><set><ref bean="moniter" />  <!--使用上面已定义好的bean --><ref bean="stu1" />     <!--使用上面已定义好的bean --><ref bean="stu1" />     <!--使用上面已定义好的bean --><bean class="com.linbingwen.Stu1"> <!--定义学生匿名内部类,用constructor方法注入 --><constructor-arg value="大平" index="0"></constructor-arg><constructor-arg value="男" index="1"></constructor-arg><constructor-arg value="10" index="2"></constructor-arg></bean><value>333333</value><value>Evankaka</value></set></property><!--map 注入例子 --><property name="mapStu"><map><entry key="key1"><ref bean="moniter" />  <!--使用上面已定义好的bean --></entry><entry key="key2"><bean class="com.linbingwen.Moniter"> <!--定义学生匿名内部类,用setter方法注入 --><property name="age" value="80" /><property name="name" value="小王" /><property name="sex" value="男" /></bean></entry><entry key="key3"><value>student2</value></entry><entry key="key4"><value>56</value></entry></map></property></bean>
</beans>

如下:

package com.linbingwen;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class Info {public static void main(String[] args) {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");Student student = (Student) applicationContext.getBean("stu1");student.printInfo();Student moniter = (Student) applicationContext.getBean("moniter");moniter.printInfo();School school=(School) applicationContext.getBean("school");school.printSchool();}}

输出结果:

四月 02, 2015 5:36:38 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@addb54: startup date [Thu Apr 02 17:36:38 CST 2015]; root of context hierarchy
四月 02, 2015 5:36:38 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [applicationContext.xml]
四月 02, 2015 5:36:38 下午 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
信息: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@ebcd03: defining beans [stu1,moniter,school]; root of factory hierarchy
姓名:飞龙
年龄:26
性别:男
姓名:欣欣
年龄:26
性别:女
--------list--------
姓名:欣欣;年龄:26;性别:女
姓名:欣欣;年龄:26;性别:女
姓名:飞龙;年龄:26;性别:男
姓名:阿屁;年龄:20;性别:男
1
hello
--------set--------
姓名:欣欣;年龄:26;性别:女
姓名:飞龙;年龄:26;性别:男
姓名:大平;年龄:10;性别:男
333333
Evankaka
--------map--------
4
key1====姓名:欣欣;年龄:26;性别:女
key2====姓名:小王;年龄:80;性别:男
key3====student2
key4====56

六、 总结

设值注入和构造注入的比较

 1、设值注入的优点

(1)与传统的JavaBean的写法更相似,更容易让人理解,依赖关系显得更加直观、自然。

(2)对于复杂的依赖关系,如果采用构造注入会导致构造器过于臃肿,难以阅读。因为Spring在创建Bean实例时,需要同时实例化其依赖的全部实例,因而导致Struts+Spring+Hibernate整合开发性能下降。设值注入可以避免这些问题。

(3)在某些属性可选的情况下,多参数的构造器更加笨重。

 2、构造注入的优点

(1) 可以在构造器中决定依赖关系的注入顺序。例如,组件中其他依赖关系的注入,常常需要依赖于Datasource的注入。采用构造注入时,可以在代码中清晰地决定注入顺序,优先依赖先注入。

(2)对于依赖关系无须变化的bean,构造注入更有用处。因为没有setter,所有的关系都在构造器中设定,因此无需担心后续代码对依赖关系产生破坏。

(3) 依赖关系只能在构造器中设定,因为只有组件的创建者才能改变组件的依赖关系。对于组件的调用者而言,组件内部的依赖关系完全透明,更符合高内聚的原则。

建议采用设值注入为主,构造注入为辅的注入策略。

Spring Bean的其他说明

1、 Bean的标识(id,name,class)

id:bean的唯一标识。

2、name:bean的别名,可以有多个。

class:bean的具体实现类

3、 Bean的作用域

(1) singleton:单例,在IOC容器里只有一个实例

<!-- 默认 -->
<beanid="loginAction"class="net.vzhang.spring3.action.LoginAction" scope="singleton"/>

(2) prototype:

<beanid="loginAction2"class="net.vzhang.spring3.action.LoginAction2" scope="prototype"/>

request:针对Web应用的每次请求都生成一个新的实例

每次对bean请求时,都会创建一个新的实例。

对bean的请求:将其注入到另外一个bean中,或者调用BeanFactory的getBean方法。

session:HttpSessio

本文工程下载

  林炳文Evankaka原创作品。转载请注明出处http://blog.csdn.net/evankaka

Spring之IOC的注入方式总结相关推荐

  1. Spring的三种注入方式(为什么推荐构造器注入?)

    Spring的三种注入方式 一.属性注入 @Resource和@Autowired的区别 为什么尽量使用 @Resource? 二.setter 注入 三.构造器注入 具体可以看看Spring官网 为 ...

  2. Spring的四种注入方式

    Spring的四种注入方式 1.set方法注入 2.构造器注入 3.静态工厂注入 4.实例工厂注入 我使用下面两个类来进行注入的演示,这两个类分别是User和Car类: Car类: public cl ...

  3. java解决框架注入,SSH框架 使用Spring时 IOC无法注入解决办法

    SSH框架 使用Spring时 IOC无法注入 本人初学JavaWeb 现在在自己做一个SSH的练习 今天遇到一个 Spring无法注入的问题, 用了一个下午的时间也没找到毛病具体发生在哪儿 求经验丰 ...

  4. spring(一):spring IoC的注入方式总结

    前言:谈谈对springIOc的理解,两张图很好的阐述了springIoc容器的作用. 传统应用程序示意图.jpg IoC容器后程序结构示意图.jpg springIoC容器注入方式有set注入,构造 ...

  5. 【Spring】Spring的IOC依赖注入的四种方式

    作者简介:大家好,我是五度鱼,一个普通的Java领域博主,不停输出Java技术博客和干货. 座右铭:锲而不舍,金石可镂. 个人主页:五度鱼学Java的主页 文章目录 前言 1. set注入 2. 构造 ...

  6. Spring的IOC创建对象的方式和代码基本解释为什么要有ioc的思维以及Ioc容器和spring依赖注入的解释

    首先我们要知道 Ioc是个啥? ​ IoC不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合.更优良的程序.传统应用程序都是由我们在类内部主动创建依赖对象,从而导致 ...

  7. Spring.Net---4、IoC/DI注入方式

    spring.net里实现了控制反转IOC(Inversion of control),也即依赖注入DI(Dependency Injection),以达到解耦的目的,实现模块的组件化.程序在调用sp ...

  8. Spring学习总结(一)——Spring实现IoC的多种方式

    一.Spring框架概述 Spring是一个开源免费的框架,为了解决企业应用开发的复杂性而创建.Spring框架是一个轻量级的解决方案,可以一站式地构建企业级应用.Spring是模块化的,所以可以只使 ...

  9. Spring选择哪种注入方式

    1. Spring常见的注入方式 1.1 Field注入 field即在变量上直接使用注解进行注入,内部使用反射的方式实现注入到field中. 优点:代码简洁有效,最为开发人员喜欢使用 缺点:依赖对象 ...

最新文章

  1. [深入学习C#]C#实现多线程的方式:使用Parallel类
  2. 小学生学python到底能干什么-颤抖 | 小学生都开始学Python了,十年后你还有工作么?...
  3. 【Unity开源项目精选】AssetStudio:提取Unity游戏的资源
  4. html垂直线6,HTML的垂直线
  5. Proj.4 API 中文参考
  6. C# EF6 更新对象
  7. yyuc php,yyuc框架介绍
  8. URI和URL、URN的作用和区别
  9. 发布、发版、上线流程
  10. 一个人写一个集群:基于GRPC的golang微服务框架iogo(grpc/protobuf/etcd/freetoo/码客 卢益贵)
  11. The error may exist in bshr/mapper/PfmMapper.xml ### The error may involve defaultParameterMap
  12. C语言核心知识点总结
  13. 用python获取某年某月/(当前)的天数
  14. r读取shape文件可视化_R语言之可视化②点图
  15. 为啥小扎一直醉心于元宇宙的布局?
  16. 史上最全的物理学科普(值得收藏)
  17. Ubuntu安装anaconda做英文词云
  18. 我走过的Charles抓包中意想不到的坑
  19. 伟大的日本数学家伊藤清去世
  20. LSM6DS3驱动编写——learn form sparkfun company

热门文章

  1. HTTP-web-Internet
  2. php和web前端工作描述,web前端岗位自我评价怎么写
  3. 性能分析系列-小命令保证大性能
  4. 网站SEO优化诊断怎么做 分析诊断报告包含了哪些内容
  5. 2018年以后正确的网站外链建设方法
  6. html页面打包为小程序
  7. python+windows11下切换输入法
  8. Ubuntu20.04的主题美化
  9. 2021-6东软云HIS医院管理信息系统V3.0-系统功能架构(门诊需求)
  10. ndk开发流程,9次Android面试经验总结,已拿offer入职