IOC(控制反转)和DI(依赖注入),这是spring的基石,Spring有了这两个机制可以帮我们省去对象的创建,销毁,初始化等工作。
SpringIOC创建对象有三种方式:
<1>采用默认的构造函数(上面的例子就是采用默认的构造函数方式,所以如果去掉默认构造方法,那么就会报错)
<2>采用静态工厂方法
<3>采用对象工厂
一个spring配置文件import另一个spring配置文件的情况:
<import resource =”applicationContext.xml_path”>
用spring容器创建的一个bean类的两个对象是同一个对象。也就是说Spring容器中默认的产生对象的scope是单例的。所以,如果把一个数据声明放到该类的属性中,那么这个数据将成为全局共享的数据。
Spring中的scope配置
* singleton 默认
* prototype 如果设置scope的属性值为此值,那么创建出来的bean对象将是多例的
scope为prototype的情况
这种情况,即使spring容器销毁了,但是该bean并没有销毁。例如Struts2中,action是多粒的,可以由spring创建,但是创建完之后不能由spring管理,而应该由struts2管理,所以spring容器销毁了,但是bean不能销毁。
Spring中的lazy-init配置
* false/default 在spring容器启动的时候创建对象。
* true bean会延迟创建对象,在context.getBean时才会创建。
如果一个bean已经在spring容器中了,并且该bean中需要大量的数据,这个时候,延迟加载稍微好点。
Spring的init和destroy方法
init-method="init",该方法是由spring容器来调用的。
destory-method="destroy",该方法也是由spring容器调用的。
当spring容器关闭的时候,或者销毁的时候,执行该方法,在该方法中可以做一些资源释放的工作。
注:spring容器管理bean的生命周期:对象的创建、初始化、销毁工作。
Spring起别名功能:
<bean id ="helloWorld" class="cn.domain.HelloWorld" lazy-init="false" init-method="init" destroy-method="destroy" ></bean>
<alias name ="helloWorld" alias="hello1" />
Spring中的依赖注入(DI)
<bean id ="person" class="cn.domain.Person">
<property name ="pid" value="1" ></property>
</bean>
@Test
public void testHello(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml" );
Person person =(Person)context.getBean( "person");
System. out.println(person.getPid());
System. out.println(person.getPname());
}
属性值为引用类型的情况
<property name ="student" >
<ref bean ="student" />
</property>
各种类型属性的赋值情况
<property name ="pid" value="1" ></property>
<property name ="pname" value="wq" ></property>
<property name ="student" >
<ref bean ="student" />
</property>
<property name ="lists" >
<list>
<value> list1</value >
<value> list2</value >
<ref bean ="student" />
</list>
</property>
<property name ="sets" >
<set>
<value> set1</value >
<ref bean ="student" />
</set>
</property>
<property name ="maps" >
<map>
<entry key ="m1" >
<value> m1</ value>
</entry>
<entry key ="m2" >
<ref bean ="student" />
</entry>
</map>
</property>
<property name ="properties" >
<props>
<prop key ="p1" >
p1
</prop>
</props>
</property>
Spring中指定构造方法创建对象的情况
public Person(String pname,Long pid){
this.pid = pid ;
this.pname =pname;
}
<bean id ="person" class="cn.tarena.domain.Person" >
<!--
用来描述构造函数的参数
index 构造函数的参数的位置,从0开始
type 构造函数的类型
value 赋值基本类型
ref 赋值一个引用
-->
<constructor-arg index ="0" value="aaa" ></constructor-arg>
<constructor-arg index ="1" value="1" ></constructor-arg>
</bean>
利用注解完成DI
<!--
启动依赖注入的注解解析器
-->
<context:annotation-config></ context:annotation-config>
@Resource注解的使用方法及原理总结:
* public class Person{
@Resource
private Student student;
}
* 配置文件
命名空间
xmlns:context ="http://www.springframework.org/schema/context
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
bean的配置
< bean id ="person" class ="cn.tarena.domain.Person" ></ bean>
< bean id ="student" class ="cn.tarena.domain.Student" ></ bean>
注解解析器
< context:annotation-config></ context:annotation-config >
注:Resource注解可以放在type、field、method上。
原理:
* 当启动Spring容器的时候因为有两个bean(person和student),所以这两个bean被实例化了。
* Spring容器会去解析
< context:annotation-config></ context:annotation-config >
* 会在纳入Spring管理的bean的范围内查找,看哪些bean的方法或者属性上添加了@Resource注解。
* 会去检查@Resource的name属性是否为"",如果为"",则会按照属性的名称和Spring的ID进行匹配,如果匹配成功,则赋值。如果匹配不成功,则会按照类型进行匹配,匹配成功,则赋值,如果不成功,则报错。如果不为"",则会按照name属性的值和Spring中的ID进行匹配,如果匹配不成功,则直接报错。
@AutoWired与@Qualifier
@Autowired
private Student student ;
注:AutoWired表示按照类型进行匹配,按照类型匹配时相当危险的。所以如果使用了这个注解,applicationContext.xml是不可以写两个类型相同的bean的。否则,就会报错,要和@Qualifier一起使用比较稳妥。一起使用相当于@Resource
类扫描机制(使配置文件中不再写bean配置)
@Component(value="p")
Spring就会创建<bean id="p"class="..Perosn">
@Component
Spring就会创建<bean id="person"class="..Person">
<context:component-scan base-package="cn.domain" ></context:component-scan>
* 下面的注释即包含了类扫描的,也包含了依赖注入的注释解析器
< context:component-scan base-package ="cn.domain" ></ context:component-scan>
* 如果想要把一个类放入到Spring容器中,则类上加一个@Component(value="*")注解
* 在属性上加@Resource(name="*")注解
原理
* 当启动Spring容器的时候,就去解析配置文件,找到
< context:component-scan base-package ="cn.domain" ></ context:component-scan>
* 就会去base-package指定的包及子包中查找类,看哪些类加了@Component注解。
* 按照@Component注解的匹配规则,去创建对象。
* 去对象中查找对应的@Resource(name="student")注解,按照@Resource(name="student")注解的匹配规则,给属性赋值。
注:xml与注解的依赖注入:
* xml写法比较复杂,但是效率比较高。
* 注解写法比较简单,但是效率比较低。
* 在xml文件中应用注解越多,效率越低。