Spring笔记(二)
Spring中Bean的配置
在Spring中,XML配置文件的根元素是
属性或子元素名称 | 说明 |
id | Bean的唯一标识符,Spring容器对Bean的配置、管理都是通过该属性进行 |
name | name属性可以为Bean指定多个名称,每个名称之间用逗号或者分号隔开 |
class | 指定Bean的实现类,必须使用全限定名称 |
scope | 用于设置Bean实例的作用域,默认为单例singleton |
constructor-arg | |
property | |
ref | |
value | |
list | 用于封装List或数组属性的依赖注入 |
set | 用于封装Set类型属性的依赖注入 |
map | 用于封装Map类型属性的依赖注入 |
entry |
在Spring的配置文件中,通常一个普通的Bean只需要定义id(或者name)和class两个属性即可。定义Bean的方式如下:
![](http://img.e-com-net.com/image/info8/2b246dbcfe82488397e9aa432bbc4e31.gif)
<bean id="bean1" class="com.ssm.Bean1"/> <bean name="bean2" class="com.ssm.Bean2"/>
如果在Bean中既没有指定id,也没有指定name,那么Spring会将class值当作id使用。
Bean的作用域
Spring 4.3中为Bean的实例定义了种作用域,其中最常用的是singleton和prototype。在Spring中,Bean的作用域是通过
singleton作用域
singleton是Spring容器默认的作用域,当Bean的作用域为singleton 时,Spring容器就只会存在一个共享的 Bean 实例,并且所有对Bean的请求, 只要 id与该Bean的id属性相匹配, 就会返回同一个 Bean的实例。 singleton作用域对于无会话状态的 Bean( 如Dao组件、Service组件)来说是最理想的选择。
1.使用idea创建一个简单的web项目,在pom文件中加入依赖,pom文件代码如下:
![](http://img.e-com-net.com/image/info8/2b246dbcfe82488397e9aa432bbc4e31.gif)
xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>com.soai.demogroupId>
<artifactId>testartifactId>
<version>1.0-SNAPSHOTversion>
<packaging>warpackaging>
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-coreartifactId>
<version>4.3.16.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-context-supportartifactId>
<version>4.3.16.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>4.3.16.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-expressionartifactId>
<version>4.3.16.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-aopartifactId>
<version>4.3.16.RELEASEversion>
dependency>
<dependency>
<groupId>commons-logginggroupId>
<artifactId>commons-loggingartifactId>
<version>1.2version>
dependency>
dependencies>
project>
2.在com.soai.demo包下建立Scope、ScopeTest类
![](http://img.e-com-net.com/image/info8/2b246dbcfe82488397e9aa432bbc4e31.gif)
package com.soai.demo; public class Scope { }
![](http://img.e-com-net.com/image/info8/2b246dbcfe82488397e9aa432bbc4e31.gif)
package com.soai.demo; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class ScopeTest { public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); for (int i = 0; i < 10; i++) { System.out.println("第" + i + "次Scope实例地址:" + applicationContext.getBean("scope")); } } }
3.在resources目录下配置applicationContext.xml
![](http://img.e-com-net.com/image/info8/2b246dbcfe82488397e9aa432bbc4e31.gif)
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd "> class="com.soai.demo.Scope"/>
4.运行ScopeTest,在控制台中姐可以看到10次取到的实例对象都是同一个,这就说明Spring容器只创建了一个Scope类的实例:
prototype作用域
对需要保持会话状态的Bean应用使用prototype作用域。在使用prototype作用域时,Spring容器会为每个对该 Bean的请求 都创建一个新的实例。
修改上面applicationContext.xml为:
![](http://img.e-com-net.com/image/info8/2b246dbcfe82488397e9aa432bbc4e31.gif)
<bean id="scope" class="com.soai.demo.Scope" scope="prototype"/>
此时再次运行ScopeTest,可以看出10次输出的Bean实例并不相同,这说明在prototype作用域下创建了10个不同的Scope实例。运行结果为:
Bean的装配方式
Bean的装配可以理解为依赖关系注入,Bean的装配方式即Bean依赖注入的方式。Spring容器支持多种方式的Bena装配,例如基于XML的装配、基于Annoation(注解)的装配、自动装配等等。
1.基于XML的装配
Spring提供了两种基于XML的装配方式:设值注入(SetterInjection)和构造注入(ConstructorInjection)。
在Spring实例化Bean的过程中,Spring首先会调用Bean的默认构造方法来实例化Bean对象,然后通过反射的方式调用setter()方法来注入属性值。因此,设值注入要求一个Bean必须满足以下两点要求:
a.Bean类必须提供一个默认的无参构造方法。
b.Bean类必须为需要注入的属性提供对应的setter()方法。
使用设值注入时,在Spring配置文件中需要使用
而使用构造注入时,在配置文件中需要使用
案例:
a.创建User类:
![](http://img.e-com-net.com/image/info8/2b246dbcfe82488397e9aa432bbc4e31.gif)
package com.soai.demo02; import java.util.List; public class User { private String userName; private String password; private ListstringList; /** *使用构造注入 * 提供带所有参数的构造方法 */ public User(String userName, String password, List stringList) { this.userName = userName; this.password = password; this.stringList = stringList; } @Override public String toString() { return "User{" + "userName='" + userName + '\'' + ", password='" + password + '\'' + ", stringList=" + stringList + '}'; } /** * 使用设值注入 * 提供默认空参构造方法 * 为所有属性提供setter方法 */ public User() { } public void setUserName(String userName) { this.userName = userName; } public void setPassword(String password) { this.password = password; } public void setStringList(List stringList) { this.stringList = stringList; } }
b.spring配置文件中分别装配按照设值注入和构造注入的两个User实例的Bean
![](http://img.e-com-net.com/image/info8/2b246dbcfe82488397e9aa432bbc4e31.gif)
<bean id="user1" class="com.soai.demo02.User" scope="prototype"> <constructor-arg index="0" value="张三"/> <constructor-arg index="1" value="123456"/> <constructor-arg index="2"> <list> <value>"这是value1"value> <value>"这是value2"value> list> constructor-arg> bean> <bean id="user2" class="com.soai.demo02.User"> <property name="userName" value="李四"/> <property name="password" value="654321"/> <property name="stringList"> <list> <value>"这是value3"value> <value>"这是value4"value> list> property> bean>
c.运行测试类:UserTest
![](http://img.e-com-net.com/image/info8/2b246dbcfe82488397e9aa432bbc4e31.gif)
package com.soai.demo02; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class UserTest { public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); System.out.println(applicationContext.getBean("user1")); System.out.println(applicationContext.getBean("user2")); } }
d.测试结果:已经成功的使用基于XML装配的构造注入和设值注入两种方式装配了User实例。
2.基于Annotation的装配
在Spring中,尽管使用XML配置文件可以实现Bean的装配工作,但如果应用中有很多Bean,就会导致XML配置文件过于臃肿,给以后的维护和升级工作带来一定的困难。为此,Spring提供了对Annotation(注解)技术的全面支持。
Spring中常用的注解:
a.@Component:可以使用此注解描述Spring中的Bean。但它是一个泛化的概念,仅仅表示一个组件(Bean),并且可以作用在任何层次。使用时只需要将该注解标注在类上即可。
b.@Repository:用于数据访问层(Dao层)的类标识为Spring中的Bean,其功能与@Component
c.@Service:经常作用在业务层(Service层),用于将业务层的类标识为Spring中的Bean,其功能与@Component
d.@Controller:经常作用在控制层(Spring MVC中的Controller),用于将控制层的类标识为Spring中的Bean,其功能与@Component
e.@Autowired(Spring的注解):用于对Bean的属性变量、属性的setter()方法及构造方法进行标注,配合对应的注解处理器完成Bean的自动装配工作。默认是按照Bean的类型(byType)进行装配,不会去匹配name。
f.@Resource(java的注解):起作用与@Autowired一样,区别在于@Autowired默认是按照Bean类型来装配,而@Resource默认是按照Bean实例名称进行装配。@Resource有两个重要的属性:name和type。Spring将name解析成为Bean实例名称,type属性解析为Bean实例类型。 若指定name属性,则按照实例名称进行装配;
若指定type,则按照Bean类型进行装配;
若都不指定,则先按Bean实例名称装配,不能匹配时再按照Bean类型进行装配;
若都无法匹配,则抛出NoSuchBeanDefinitionException异常
g.@Qualifier:与@Autowired注解配合使用,会将默认的按Bean类型装配修改为按Bean的实例名称装配,Bean的实例名由@Qualifier注解的参数指定
注意:虽然@Repository、@Service和@Controller的功能与@Component注解的功能相同,但为了使标注类本身用途更加清晰,建议在实际开发中使用@Repository、@Service和@Controller分别对实现类进行标注。在接口仅有单一实现类时,@Autowired与@Resource两个注解的修饰效果相同,可以互相替换,不影响使用。
与基于XML方式的注解不同的是:在
使用注解装配Bean的方式一定程度上减少了配置文件中的代码量。
3.自动装配
如何再以上装配方式的情况下,继续再次减少代码量呢?Spring中的
a.default:由
![](http://img.e-com-net.com/image/info8/2b246dbcfe82488397e9aa432bbc4e31.gif)
<--其子元素>的autowire属性对应的属性值也是byName--> <beans default-autowire="byName">
b.byName:根据属性的名称自动装配。容器按照名称查找与属性完全一致的Bean,并将其属性自动装配
c.byType:根据属性的数据类型自动装配,如果一个Bean的数据类型兼容另一个Bean中属性的数据类型(兼容包括继承和接口实现类),则自动装配
d.constructor:根据构造函数参数的数据类型进行byType模式的自动装配
e.no:在默认情况下,不使用自动装配,Bean依赖必须通过ref元素定义
End