从工作开始到现在一直都有使用Spring,日常开发中总有spring的身影,但实话实讲,对spring的认识一直停留在使用阶段,只知其然。做技术当然不能这样,柄着知其所以然的态度,想系统的学习分析一下spring,无奈懒惰让我一直没有着手做。不积跬步,无以至千里,万事得开个头,终于下定决定写下第一篇。
tip: 本系列根据spring 5.2.6.RELEASE
进行分析。
引入spring依赖
1 2 3 4 5 6 7 8 9 10 11 12
| <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>5.2.6.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.6.RELEASE</version> </dependency>
|
传统应用程序可以通过new和反射方式进行实例化Bean。而Spring IOC容器则需要根据Bean定义里的配置元数据使用反射机制来创建Bean。在Spring IOC容器中根据Bean定义创建Bean主要有以下几种方式:
- 使用构造器或setter方法实例化Bean
这是最简单的方式,Spring IoC容器即能使用默认空构造器也能使用有参数构造器两种方式创建Bean,如以下方式指定要创建的Bean类型
使用空构造器进行定义,使用此种方式,class属性指定的类必须有空构造器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| package com.study.ioc.model;
public class People { private String name;
private int age;
public People() { }
public People(String name, int age) { this.name = name; this.age = age; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
@Override public String toString() { return "People{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
|
1 2 3
| <bean id="people" class="com.study.ioc.model.People">
|
使用有参数构造器进行定义,使用此中方式,可以使用< constructor-arg>标签指定构造器参数值,其中index表示位置,value表示常量值,也可以指定引用,指定引用使用ref来引用另一个Bean定义;
1 2 3 4 5 6
| <bean id="people" class="com.study.ioc.model.People"> <constructor-arg index="0" value="normPeople"/> <constructor-arg index="1" value="18"/> </bean>
|
或者写上对应的set、get方法,然后再bean.xml文件中利用property注入值即可。
1 2 3 4 5
| <bean id="setterPeople" class="com.study.ioc.model.People"> <property name="name" value="setterPeople"/> <property name="age" value="18"/> </bean>
|
- 使用静态工厂方式实例化Bean
使用这种方式除了指定必须的class属性,还要指定factory-method属性来指定实例化Bean的方法,而且使用静态工厂方法也允许指定方法参数,spring IoC容器将调用此属性指定的方法来获取Bean:
1 2 3 4 5 6 7 8 9 10
| package com.study.ioc.model;
public class PeopleStaticFactory {
public static People newPeopleInstance(String name, int age) { return new People(name, age); }
}
|
1 2 3 4 5
| <bean id="factoryPeople" class="com.study.ioc.model.PeopleStaticFactory" factory-method="newPeopleInstance"> <constructor-arg index="0" value="factoryPeople"/> <constructor-arg index="1" value="18"/> </bean>
|
- 使用实例工厂方法实例化Bean
使用这种方式不能指定class属性,此时必须使用factory-bean属性来指定工厂Bean,factory-method属性指定实例化Bean的方法,而且使用实例工厂方法允许指定方法参数,方式和使用构造器方式一样。
1 2 3 4 5 6 7 8 9
| package com.study.ioc.model;
public class PeopleInstanceFactory {
public People newPeopleInstance(String name, int age) { return new People(name, age); } }
|
1 2 3 4 5 6 7 8
|
<bean id="peopleInstanceFactory" class="com.study.ioc.model.PeopleInstanceFactory"/>
<bean id="instancePeople" factory-bean="peopleInstanceFactory" factory-method="newPeopleInstance"> <constructor-arg index="0" value="instancePeople"/> <constructor-arg index="1" value="18"/> </bean>
|
- 实现FactoryBean接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| package com.study.ioc.model;
import org.springframework.beans.factory.FactoryBean;
public class PeopleFactory implements FactoryBean<People> { public People getObject() throws Exception { People people = new People(); people.setName("weylan"); people.setAge(18); return people; }
public Class<?> getObjectType() { return People.class; }
public boolean isSingleton() { return true; }
@Override public String toString() { return "PeopleFactory{}"; } }
|
xml中只需定义FactoryBean即可
1
| <bean id="peopleFactory" class="com.study.ioc.model.PeopleFactory"/>
|
在我们调用getBean("peopleFactory")
时,会返回一个People对象,而如果需要返回FactoryBean
本身,则只需要使用getBean("&peopleFactory")
即可。
FactoryBean在阅读Spring源码时经常可以见到,是很重要一个接口。
测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); People people = (People) ctx.getBean("people"); System.out.println(people);
People factoryPeople = (People) ctx.getBean("factoryPeople"); System.out.println(factoryPeople);
People instancePeople = (People) ctx.getBean("instancePeople"); System.out.println(instancePeople);
People setterPeople = (People) ctx.getBean("setterPeople"); System.out.println(setterPeople);
People people = (People) ctx.getBean("peopleFactory"); System.out.println(people);
PeopleFactory peopleFactory = (PeopleFactory) ctx.getBean("&peopleFactory"); System.out.println(peopleFactory);
}
|
结果:
1 2 3 4 5 6 7
| People{name='normPeople', age=18} People{name='factoryPeople', age=18} People{name='instancePeople', age=18} People{name='setterPeople', age=18} People{name='weylan', age=18} PeopleFactory{}
|