记录自己学习Spring的历程,参考书:spring in action
首先自建一个SpringMVC项目;自建项目过程中遇到两个eclipse的问题:
1. 创建maven项目,但是没有webContent文件
右键项目-》Properties-》Project Facets-》Dynamic Web Module
2. WebContent文件下没有web.xml
右键项目-》Java EE Tools-》Generate Deployment Descriptor Stub
我的maven依赖配置:
-
<dependencies>
-
<dependency>
-
<groupId>org.springframework
</groupId>
-
<artifactId>spring-web
</artifactId>
-
<version>4.1.2.RELEASE
</version>
-
<scope>compile
</scope>
-
</dependency>
-
<dependency>
-
<groupId>org.springframework
</groupId>
-
<artifactId>spring-webmvc
</artifactId>
-
<version>4.1.2.RELEASE
</version>
-
<scope>compile
</scope>
-
</dependency>
-
<dependency>
-
<groupId>org.springframework
</groupId>
-
<artifactId>spring-test
</artifactId>
-
<version>4.1.2.RELEASE
</version>
-
<scope>compile
</scope>
-
</dependency>
-
<dependency>
-
<groupId>junit
</groupId>
-
<artifactId>junit
</artifactId>
-
<version>4.12
</version>
-
<scope>test
</scope>
-
</dependency>
-
</dependencies>
Spring装配Bean有3中方式:
1.自动化配置
2.JavaConfig
3.XML
自动化配置:
1.在java中配置自动扫描,默认扫面当前包以及当前包下的所有子包
@Configuration @ComponentScan public class CDPlayerConfig { }指定扫描的基础包
@ComponentScan("com.spring")
还可以表明设置的基础包
@ComponentScan(basePackages={"com.spring","com.jpa"})
以上都是通过String指定基础包,这种方法有可能是不安全的(没有理解),如果重构代码的话,所有指定的基础包有可能出现错误,所以可以这样(这些类所在的包将会作为扫描的基础包):
@Component(basePackageClasses={My.class,She.class})
2.在XML中配置自动扫描
<!-- 开启注解自动扫描 --> <context:component-scan base-package="com.lcf.spring"/>在当前情况下,所有存在@Component注解的类,都会被自动扫描为bean,如果没有指定bean的id,那么bean的id将会以类名首字母小写的方式存在。
@Component public class SqtPeppers implements CompactDisc { }指定bean的id:
@Component("sqt")
自动装配就是让Spring自动满足bean依赖的方法,借助@Autowired注解。
可以用在构造器上:
@Autowired public CDPlayer(SqtPeppers sqt){ this.sqt = sqt; }可以用在setter方法上:
@Autowired public void setSqtPeppers(SqtPeppers sqt){ this.sqt = sqt; }可以用在属性上:
@Autowired private SqtPeppers sqt;以上都可以实现自动装配,但是如果没有匹配的bean装配,那么在应用上下文创建时,Spring抛出异常。为了避免异常:
@Autowired(required=false)
如果没有匹配成功,将会让该bean处于未匹配状态。
通过java代码装配bean
@Configuration //@ComponentScan public class CDPlayerConfig { @Bean(name="sqt") public CompactDisc sqtPeppers(){ return new SqtPeppers(); } @Bean public MediaPlay cdPlay(){ return new CDPlayer(new SqtPeppers()); } }javaConfig中去出了@ComponentScan注解,转而使用方法配合@Bean注解的方式获取bean;默认是bean的id就是方法名,因为sqtPeppers()方法上有@Bean注解,所以在cdPlay()方法中调用的new对象会被Spring拦截,直接返回相应的bean。
其实可以这么写(一样的):
@Bean public MediaPlay cdPlay(CompactDisc compactDisc){ return new CDPlayer(compactDisc); }
通过XML配置bean
声明一个简单的bean:
<bean class="com.lcf.spring.fitoutBean.SqtPeppers"/>
由于没有给定Id,所以这里使用了全限定类名指定ID,此时bean的ID为“com.spring.CDPlayer#0,其中#0是一个计数形式,用于区分相同类型的不同bean。
指定id:
<bean id="sqt" class="com.lcf.spring.fitoutBean.SqtPeppers"/>
借助构造器注入初始化bean:
1. <constructor-arg>元素
<bean class="com.lcf.spring.fitoutBean.CDPlayer" >
<constructor-arg ref="sqt"/></bean>
2. 使用Spring3.0引入的c-命名空间:
需要在XML的顶部声明其模式
xmlns:c="http:www.springframework.org/schema/c"
在c-命名空间声明后,可以使用来声明构造参数
-
<bean class="com.lcf.spring.fitoutBean.CDPlay"
-
c:sqt-ref=
"sqt"
-
/>
上述使用构造参数时,直接引用了构造参数的名称“sqt”,还支持位置引用的方式
-
<bean class="com.lcf.spring.fitoutBean.CDPlay"
-
c:_0-ref=
"sqt"
-
/>
XML中不允许数字作为第一个字符,所以使用了下划线。
当只有一个构造参数时,我们也可以简写:
-
<bean class="com.lcf.spring.fitoutBean.CDPlay"
-
c:_-ref=
"sqt"
-
/>
迄今为止,做到的都是引用注入,接下来注入字面量(value):
-
<bean id="blank" class="com.lcf.spring.fitoutBean.BlankDisc">
-
<constructor-arg value="Sgt. Pepper`s Lonely hearts Club band"/>
-
<constructor-arg value="The Beatles"/>
-
</bean>
也可以使用c-命名空间:
-
<bean class="com.lcf.spring.fitoutBean.BlankDisc"
-
c:_title=
""
-
c:_artist=
""
-
/>
-
<bean class="com.lcf.spring.fitoutBean.BlankDisc"
-
c:_0=
""
-
c:_1=
""
-
/>
当只有一个参数时,也可以简写:
-
<bean class="com.lcf.spring.fitoutBean.BlankDisc"
-
c:_=
""
-
/>
引用和字面量的装配,对于c-命名空间或者<constructor-arg>是没有区别的,但是一下的装配是c-命名空间做不到的。
装配集合:
-
<bean id="blank" class="com.lcf.spring.fitoutBean.BlankDisc">
-
<constructor-arg value="Sgt. Pepper`s Lonely hearts Club band"/>
-
<constructor-arg value="The Beatles"/>
-
<constructor-arg>
-
<list>
-
<value>
</value>
-
<value>
</value>
-
<value>
</value>
-
</list>
-
</constructor-arg>
-
</bean>
我们也可以使用ref代替value代表引用,使用Set时替换<list>为<set>,<set>会忽略重复的元素,并且不能保证顺序,学习Spring in action时,是无法使用c-命名空间声明集合的。
以上完全是通过构造器注入,接下来使用setter注入的方式:
-
<bean class="com.lcf.spring.fitoutBean.CDPlayer" >
-
<property name="sqtPeppers" ref="sqt">
</property>
-
</bean>
强依赖使用构造器注入,可选性依赖使用setter注入。
使用p-命名空间,与c-命名空间的用法类似,p-命名空间为了简写<property>标签。
声明p-命名空间:
xmlns:p="http:www.springframework.org/schema/c"
使用p-命名空间进行setter注入:
-
<bean class="com.lcf.spring.fitoutBean.CDPlayer"
-
p:sqt-ref=
"sqt"
-
/>
注入字面量时,与构造器注入类似,将<contructor-arg>替换为<property>即可。
p-命名空间也无法装配集合。
使用util-命名空间:
首先声明util:
-
<?xml version="1.0" encoding="UTF-8"?>
-
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-
xmlns:c=
"http://www.springframework.org/schema/c"
xmlns:p=
"http://www.springframework.org/schema/c"
xmlns:util=
"http://www.springframework.org/schema/util"
-
xsi:schemaLocation=
"
-
http://www.springframework.org/schema/context
-
http://www.springframework.org/schema/context/spring-context.xsd
-
http://www.springframework.org/schema/beans
-
http://www.springframework.org/schema/beans/spring-beans.xsd
-
http://www.springframework.org/schema/util
-
http://www.springframework.org/schema/util/spring-util.xsd">
使用util-命名空间可以声明list、set元素:
-
<util:list id="trackList">
-
<vlaue>
</vlaue>
-
<vlaue>
</vlaue>
-
<vlaue>
</vlaue>
-
</util:list>
bean的属性注入集合。