一、初识Spring之Ioc
Spring是一个轻量级的企业级开源框架,Spring框架的核心是一个Ioc容器。Ioc (Inversion of Control)又称"控制反转",是面向对象编程中的一种设计原则,用来降低程序代码之间的耦合度。
实战演练:使用Spring Ioc实现业务层和数据访问层解耦合。
1.定义数据访问层接口:UserDao
1
2
3
4
5
6
7
8
9
10
|
package
com.jbit.fsd.dao;
import
java.util.List;
import
com.jbit.fsd.entity.User;
public
interface
UserDao {
public
List<User> getAll();
}
|
2.定义了业务访问层接口:UserService
1
2
3
4
5
6
7
8
9
10
|
package
com.jbit.fsd.service;
import
java.util.List;
import
com.jbit.fsd.entity.User;
public
interface
UserService {
public
List<User> getAll();
}
|
3.定义了数据访问层接口实习类:UserDaoImpl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
package
com.jbit.fsd.dao.impl;
import
java.util.ArrayList;
import
java.util.List;
import
com.jbit.fsd.dao.UserDao;
import
com.jbit.fsd.entity.User;
public
class
UserDaoImpl
implements
UserDao {
@Override
public
List<User> getAll() {
//操作数据库读到所有数据
List<User> list=
new
ArrayList<User>();
list.add(
new
User());
list.add(
new
User());
list.add(
new
User());
return
list;
}
}
|
4.定义数据访问层接口实现类:UserServiceImpl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
package
com.jbit.fsd.service.impl;
import
java.util.List;
import
com.jbit.fsd.dao.UserDao;
import
com.jbit.fsd.entity.User;
import
com.jbit.fsd.service.UserService;
public
class
UserServiceImpl
implements
UserService{
private
UserDao dao;
//通过spring注入进来
public
void
setDao(UserDao dao) {
this
.dao = dao;
}
@Override
public
List<User> getAll() {
// TODO Auto-generated method stub
return
dao.getAll();
}
}
|
5.在spring配置文件中配置Bean并注入业务实现类UserServiceImpl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
<?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:aop=
"http://www.springframework.org/schema/aop"
xmlns:tx=
"http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http:
//www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http:
//www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http:
//www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<!-- 以面向接口思想编程实现解耦和 -->
<bean id=
"userDao"
class
=
"com.jbit.fsd.dao.impl.UserDaoImpl"
>
</bean>
<bean id=
"userServiceImpl"
class
=
"com.jbit.fsd.service.impl.UserServiceImpl"
>
<!-- 需要注意是是这里调用setDao()方法 -->
<property name=
"dao"
ref=
"userDao"
></property> <!-- 属性注入 -->
</bean>
</beans>
|
6.测试类入口:
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
|
package
com.jbit.fsd.test;
import
java.util.List;
import
org.springframework.context.ApplicationContext;
import
org.springframework.context.support.ClassPathXmlApplicationContext;
import
com.jbit.fsd.dao.UserDao;
import
com.jbit.fsd.entity.User;
import
com.jbit.fsd.service.UserService;
public
class
Test {
/**
*
* Description:
* @param
* @author xiazhongwei
* @data 2016:下午12:18:37
* @return
*/
public
static
void
main(String[] args) {
ApplicationContext ac=
new
ClassPathXmlApplicationContext(
"applicationContext.xml"
);
UserService service=(UserService) ac.getBean(
"userServiceImpl"
);
List<User> list=service.getAll();
System.out.println(list.size()+
"********************"
);
}
}
|
上面的小例子需要Spring核心jar的支持:可到官网下载
说明:
1.Spring为dao属性赋值是通过setDao()方法实现的,而非直接为dao属性赋值,若属性为dao,但是setter方法为setUserDao,Spring配置文件应该写成name="userDao",而非name="dao";
2.除了使用ApplicationContext及其实现类,还可以通过BeanFactory接口实现类对Bean组件实施管理,ApplicationContext建立在BeanFactory的基础之上,可以对企业级开发提供更全名的支持。
使用上面的方法通过spring的setter访问器实现对属性的赋值,这种方法称设置注入,除此之外,spring还提供了通过构造方法赋值,这种称构造注入。
定义业务实现类UserServiceImplByConstructor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
package
com.jbit.fsd.service.impl;
import
java.util.List;
import
com.jbit.fsd.dao.UserDao;
import
com.jbit.fsd.entity.User;
import
com.jbit.fsd.service.UserService;
public
class
UserServiceImplByConstructor
implements
UserService {
private
UserDao dao;
// 定义有参的构造方法JVM不会自定义无参的构造方法,需要手动加入
public
UserServiceImplByConstructor(){
}
// 用于为dao属性赋值的构造方法
public
UserServiceImplByConstructor(UserDao dao){
this
.dao = dao;
}
@Override
public
List<User> getAll() {
return
dao.getAll();
}
}
|
spring配置文件中的配置:
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
|
<?xml version=
"1.0"
encoding=
"UTF-8"
?>
<!--
- Application context definition
for
JPetStore's business layer.
- Contains bean references to the transaction manager and to the DAOs in
- dataAccessContext-local/jta.xml (see web.xml's
"contextConfigLocation"
).
-->
<beans xmlns=
"http://www.springframework.org/schema/beans"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop=
"http://www.springframework.org/schema/aop"
xmlns:tx=
"http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http:
//www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http:
//www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http:
//www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<!-- 以面向接口思想编程实现解耦和 -->
<bean id=
"userDao"
class
=
"com.jbit.fsd.dao.impl.UserDaoImpl"
>
</bean>
<bean id=
"userServiceImplByConstructor"
class
=
"com.jbit.fsd.service.impl.UserServiceImplByConstructor"
>
<!-- 通过定义的单参数构造为业务层的dao属性赋值 -->
<constructor-arg>
<!-- 引用id为userDao的对象为dao属性赋值 -->
<ref bean=
"userDao"
/>
</constructor-arg>
</bean>
</beans>
|
说明:一个<constructor-arg>元素表示一个构造参数,且使用时不区分顺序,当构造方法的参数出现混淆,无法区分时,可以通过<constructor-arg>元素的index属性来指定该参数的位置索引,位置从0开始,<constructor-arg>元素还提供了type属性用来指定参数的类型,避免字符串和基本类型的混淆。
二、不同类型参数的注入方法
1.注入直接量(基本类型、字符串)
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
38
39
40
41
42
43
|
<?xml version=
"1.0"
encoding=
"UTF-8"
?>
<!--
- Application context definition
for
JPetStore's business layer.
- Contains bean references to the transaction manager and to the DAOs in
- dataAccessContext-local/jta.xml (see web.xml's
"contextConfigLocation"
).
-->
<beans xmlns=
"http://www.springframework.org/schema/beans"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop=
"http://www.springframework.org/schema/aop"
xmlns:tx=
"http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http:
//www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http:
//www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http:
//www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<!-- 以面向接口思想编程实现解耦和 -->
<bean id=
"userDao"
class
=
"com.jbit.fsd.dao.impl.UserDaoImpl"
>
</bean>
<bean id=
"userServiceImpl"
class
=
"com.jbit.fsd.service.impl.UserServiceImpl"
>
<!-- 需要注意是是这里调用setDao()方法 -->
<span style=
"color: rgb(255, 0, 0);"
><property name=
"dao"
ref=
"userDao"
></property> </span> <!-- 属性注入 -->
</bean>
<bean id=
"userServiceImpl"
class
=
"com.jbit.fsd.service.impl.UserServiceImpl"
>
<property name=
"username"
>
</property>
<!-- 注入直接量 -->
<value>张三</value>
</bean>
<bean id=
"userServiceImpl"
class
=
"com.jbit.fsd.service.impl.UserServiceImpl"
>
<!-- 需要注意是是这里调用setDao()方法 -->
<span style=
"color: rgb(255, 0, 0);"
><property name=
"dao"
>
<ref local=
"userDao"
></ref>
</property></span>
</bean>
<bean id=
"userServiceImplByConstructor"
class
=
"com.jbit.fsd.service.impl.UserServiceImplByConstructor"
>
<!-- 通过定义的单参数构造为业务层的dao属性赋值 -->
<constructor-arg>
<!-- 引用id为userDao的对象为dao属性赋值 -->
<ref bean=
"userDao"
/>
</constructor-arg>
</bean>
</beans>
|
上面的代码看:local属性和bean属性的用法和像,区别在于:当把spring的配置文件拆分为多个时,使用local属性只能在同一个配文件中检索Bean的id,而使用bean属性可以在其他配置文件中检索id。
2.使用内部Bean
1
2
3
4
5
6
|
<bean id=
"userServiceImpl"
class
=
"com.jbit.fsd.service.impl.UserServiceImpl"
>
<!-- 需要注意是是这里调用setDao()方法 -->
<property name=
"dao"
>
<bean
class
=
"com.pb.dao.impl.UserDaoimpl"
>
</property> <!-- 属性注入 -->
</bean>
|
如果属性中包含特殊字符如(&,<,>)等可将特殊字符替换为实体引用,如<替换为&It.
3.注入集合类型的属性
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
38
39
|
<?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:aop=
"http://www.springframework.org/schema/aop"
xmlns:tx=
"http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http:
//www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http:
//www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http:
//www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<!-- 以面向接口思想编程实现解耦和 -->
<bean id=
"userDao"
class
=
"com.jbit.fsd.dao.impl.UserDaoImpl"
>
</bean>
<bean id=
"user"
class
=
"com.pb.eneity.User"
>
<property name=
"hobbies"
><br> <!--list类型变量的注入 -->
<list>
<value>足球</value>
<value>篮球</value>
</list>
</property>
</bean>
<bean id=
"user"
class
=
"com.pb.eneity.User"
>
<property name=
"hobbies"
><br> <!--ser类型变量的注入-->
<set>
<value>足球</value>
<value>篮球</value>
</set>
</property>
</bean>
<bean id=
"user"
class
=
"com.pb.eneity.User"
>
<property name=
"hobbies"
><br> <!-- map类型变量的注入 -->
<map>
<entry>
<key><value>username</value></key>
<ref bean=
"com.pb.entity.User"
></ref>
</entry>
</map>
</property>
</bean>
</beans>
|
三、使用多种方式简化spring Ioc的配置
1.使用p命名空间注入Bean属性
使用p命名空间改进配置,改进前先添加p命名空间是声明。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
<?xml version=
"1.0"
encoding=
"UTF-8"
?>
<!--
- Application context definition
for
JPetStore's business layer.
- Contains bean references to the transaction manager and to the DAOs in
- dataAccessContext-local/jta.xml (see web.xml's
"contextConfigLocation"
).
-->
<beans xmlns=
"http://www.springframework.org/schema/beans"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop=
"http://www.springframework.org/schema/aop"
xmlns:tx=
"http://www.springframework.org/schema/tx"
<span style=
"color: rgb(255, 0, 0);"
>xmlns:aop=
"http://www.springframework.org/schema/p"
</span>
xsi:schemaLocation="
http:
//www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http:
//www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http:
//www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<bean id=
"userDao"
class
=
"com.jbit.fsd.dao.impl.UserDaoImpl"
<span style=
"color: rgb(255, 0, 0);"
> p:age=
"18"
p:username=
"xiaoming"
</span>>
</bean>
</beans>
|
使用p命名空间简化配对效果明显,使用语法总结:
1.对于直接量(基本数据类型、字符串)属性,使用方式如下:
p:属性名=“属性值”
2.对于引用Bean的属性,使用方式如下:
p:属性名-ref="Bean的id"
2.Spring配置文件实现自动装配
<bean>元素的autowire属性提供了一种自动注入的依赖对象的机制,配置Bean时不需要做任何显示的指定,spring会自动查找符合条件的依赖对象并实施注入。
<bean id="userService" class="com.pb.serviceImp.UserServiceImpl" autowire="byType">
spring提供了几种自动装配的类型:
1.no:默认值,Spring默认不进行自动装配,必须显示的指定依赖对象
2.byName: 根据属性名自动装配,Spring自动查找与属性名相同的id,如果找到,则自动注入,否则什么也不做。
3.byType:根据属性的类型自动装配,Spring自动查找与属性类型相同Bean,如果找到唯一的那个,则自动注入,如果找到多个与属性类型相同的Bean,则抛出异常,如果没找到则什么也不做。
4.constructor:和byType类似,不过他针对构造方法,如果spring找到一个Bean和构造方法的参数类型像匹配,则通过构造方法注入到依赖对象,如果没有,则抛异常。
如果每个Bean都设置autowire属性也是挺麻烦的,spring提供了default-autowire属性,设置全局的自动装配。
1
2
3
4
5
6
7
8
9
10
|
<beans xmlns=
"http://www.springframework.org/schema/beans"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop=
"http://www.springframework.org/schema/aop"
xmlns:tx=
"http://www.springframework.org/schema/tx"
xmlns:aop=
"http://www.springframework.org/schema/p"
xsi:schemaLocation="
http:
//www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http:
//www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http:
//www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"
default
-autowire=
"byType"
>
|