Spring框架入门教程.docx
《Spring框架入门教程.docx》由会员分享,可在线阅读,更多相关《Spring框架入门教程.docx(51页珍藏版)》请在冰豆网上搜索。
Spring框架入门教程
Spring基础入门
一、基础知识
1.依赖注入、控制反转
依赖注入:
在运行期,由外部容器动态地将依赖对象注入到组件中
控制反转:
应用本身不负责依赖对象的创建及维护,依赖对象的创建及维护是由外部窗口负
责得。
这样控制权就由应用转移到了外部容器,控制权的转移就是所谓的反转。
2.spring的主要特性。
(1)降低组件之间的耦合度,实现软件各层之间的解耦。
(2)可以使用容器提供的众多服务,如:
事务管理服务、消息服务、JMS服务、持久化服
务等等。
(3)容器提供单例模式支持,开发人员不再需要自己编写实现代码。
(4)容器提供了AOP技术,利用它很容易实现如权限拦截,运行期监控等功能。
(5)容器提供的众多辅作类,使用这些类能够加快应用的开发,如:
JdbcTemplate、
HibernateTemplate.
(6)对主流的应用框架提供了集成支持。
3.常用技术
控制反转/依赖注入---面向切入编程---与主流框架的整合、管理---
二、实例拓展
1.准备搭建环境
dist\spring.jar
lib\jakata-commons\commons-loggin.jar
如果使用了切面编程,还需下列jar文件:
lib\aspectj\aspectjweaver.jar和aspectjrt.jar
lib\cglib\cglib-nodep-2.1.3.jar
如果使用了jsr-250中的注解,还需要下列jar文件:
lib\j2ee\common-annotations.jar
2.搭建并测试环境
建立名为spring_01_base项目,根据需求导入jar包。
建立一个Junit测试单元
SpringEnvTest,测试代码如下:
@Test
publicvoidtestEnv(){
ApplicationContextctx=new
ClassPathXmlApplicationContext("beans.xml");
}
beans.xml配置文件在此省略(见下)。
运行此测试如无错,则说明环境搭建成功。
说明:
beans.xml可以在类路径下进行配置,也可以在具体的目录下配置。
可以是一个配置文
件,也可以是多个配置文件组成String数组传入。
3.实例
作如下准备工作:
(1)建立UseDao接口,代码如下:
packagecom.asm.dao;
publicinterfaceUserDao{
voidsave();
}
(2)建立UserDao接口的实现类,UserDaoImpl
packagecom.asm.dao.impl;
importcom.asm.dao.UserDao;
publicclassUserDaoImplimplementsUserDao{
publicvoidsave(){
System.out.println("执行save方法...");
}
}
(3)在src目录下配置此beans.xml,它的配置如下:
xmlversion="1.0"encoding="UTF-8"?
>
xmlns:
xsi=""
xsi:
schemaLocation="
">
说明:
bean代表一个实质的java类,通过它的id可以获取一个此类的一个对象。
补充:
让xml配置文件在编译时提示
[windows][preferences][myeclipse][filesandeditors][xml][xmlcatalog]点add,
在出现窗口的location中选“”,然后在spring解压目录的dist/resources
目录中选择“spring-beans-2.5.xsd”,并将keyType值改为“SchemaLocation”,key值
为:
(4)Junit测试单元SpringEnvTest中增加如下代码测试:
@Test
publicvoidbase(){
ApplicationContextctx=new
ClassPathXmlApplicationContext("beans.xml");
UserDaouserDao=(UserDao)ctx.getBean("userDaoImpl");
userDao.save();
}
以上的代码就是通过配置文件beans.xml获取所需要的实例对象。
4.三种bean的生成方式
除了上面使用的类直接生成方式,还有bean静态工厂及bean实例工厂。
bean静态工厂的配置如下:
factory-method="getUserDaoImpl"/>
相应的工厂类代码如下:
packagecom.asm.dao.impl;
publicclassUserDaoImplFactory{
publicstaticUserDaoImplgetUserDaoImpl(){
returnnewUserDaoImpl();
}
}
bean实例工厂的配置如下:
factory-method="getUserDaoImpl"/>
相应的工厂类的代码如下:
packagecom.asm.dao.impl;
publicclassUserDaoImplFactory2{
publicUserDaoImplgetUserDaoImpl(){
returnnewUserDaoImpl();
}
}
5.bean的作用域
singleton:
返回bean的同一个实例,也是默认的作用域(无状态bean使用此作用域)
prototype:
每次请求都会创建一个实例(有状态bean使用此作用域)
request、session、globalsession这三个作用域主要用在web应用中
6.bean的生命周期
(1)什么时候初始化bean实例
当scope=singleton,即默认情况,会在装载配置文件时实例化。
如果希望在调用getBean
时才初始化,可以使用lazy-init="true"补充:
如果希望希望该配置文件中的所有bean
都延迟初始化,则应在beans根结点中使用lazy-init="true"。
当scope=prototype时,在调用getBean()方法时才会初始化。
(2)生命周期:
构造器、init方法、获取bean后的操作、destroy方法(ctx.close、注意如果bean的scope
设为prototype时,当ctx.close时,destroy方法不会被调用)
7.属性注入Setter方式
(1)简单属性(如String):
(2)对象属性-外部bean注入:
在上面的中增加如下配置:
对象属性-内部bean注入:
在上面的中增加如下配置:
(3)集合属性注入:
List值一
List值二
List值三
Set值二
Set值一
Set值三
first
second
third
注意:
在相应的字段上一定要有setter方法,才能注入。
补充:
使用继承。
在beans.xml中的配置如下:
相当于在XXXbean实例中也有username属性设置。
8.属性注入构造器方式
List值一
List值二
List值三
UserServiceBean对应的构造方法代码如下:
publicUserServiceBean(Stringusername,UserDaouserDao,Setset)
{
this.username=username;
this.userDao=userDao;
this.set=set;
}
注意:
此方法会覆盖掉默认的构造方法,导致要依赖默认构造方法的配置不可用,因此我们还应
为此类提供一个默认的构造器。
三、使用注解方式注入
1.准备
注解方式的注入主要针对对象属性的注入。
使用注解功能要引用注解包,另beans.xml的配置模板如下:
xmlversion="1.0"encoding="UTF-8"?
>
xmlns:
xsi=""
xmlns:
context=""
xsi:
schemaLocation="
"
>
annotation-config/>
--开启注解功能-->
2.Resource注解实例
拷贝上一个项目为spring_02_annotation项目,修改UserServiceBean为如下形式:
packagecom.asm.service;
publicclassUserServiceBean{
@Resource(name="userDaoImpl")
privateUserDaouserDao;
privateUserDaouserDao2;
@Resource
publicvoidsetUserDao2(UserDaouserDao2){
this.userDao2=userDao2;
}
publicvoidtest(){
userDao.save();
userDao2.save();
}
}
然后在bean.xml中的配置如下:
简要说明:
Resouce注解可以在字段上标记,也可以在对应的setter方法上标记。
此注解可
以不使用name属性,它会自动去查找匹配的类型(先以字段名称为name的值查找,如找不到
会再根据依赖对象的类型查找)。
但只要使用了name属性,就应确保name的值在xml中有相应
的beanId对应。
它是属于java本身的注解,Resource默认按属性名称装配
3.Autowired注解实例
@Autowired(required=false)
@Qualifier("userDaoImplXXX")
privateUserDaouserDao3;
说明:
Autowired默认是按照类型来查找对应的bean实例注入,如果想注入指定名称的bean
实例,可以使用Qualifier注解来指定名字。
Required属性设为true时,如果不能成功注
入则会报告异常,如果为设为false而不能成功注入,则会将userDao3设为null。
同样地,
它也实用于setter方法。
它属于spring特有的注解,Autowired默认按类型装配。
4.自动装配
自动装配(了解,不建议使用):
除了要设置字段的setter方法外,还应在beans.xml配置文
件中设置如下内容:
class="com.asm.service.UserServiceBean2"autowire="byType"/>
说明:
除了byType外,autowire的可选属性如下:
byName:
根据类中的字段名来查找对应的bean,如不能成功注入,则字段设为null.
byType:
根据类型装配,如果发现多个类型都能够匹配,则抛出异常。
Consturctor:
也byType相似,不同之处在于它应用于构造器的参数,如果容器中没有找到
与构造器参数类型一致的bean,则抛出异常。
Autodetect:
通过bean类的自省机制来决定是使用consturctor还是byType方式进行自动装
配。
如果发现默认的构造器,那么将使用byType方式。
四、自动扫描管理bean
1.准备工作
在前面使用注解的时候,除了结点配置增加了名称空间说明,另还增加了
annotation-config/>配置,它的作用就是注册一个处理器。
通常情况下,我
们要使用某个bean实例,总会配置相关内容。
Spring最新版本可以简化这一操作,即
是说我们只要在配置文件作如下设置:
component-scanbase-package="包名"/>便可以自动管理指定包名及子包
下标住了@service(业务层组件)、@controller(控制层组件)、@repository(数据访问
组件)或@component(泛指组件)的类,并把它们作一个实例bean,相当于在beans.xml中配
置了元素。
需要说明的是,使用了此配置同时意味着还注册了注解配置的处理器,所
以在这些类中用到了注解配置时并不需要再配置annotation-config/>。
为什么提出自动扫描管理:
在一些比较大的项目中,涉及到的bean实例会有很多,如果依次
对每个bean实例进行配置,不但配置内容繁琐,而且配置文件也会显得杂乱。
因此spring
提出了自动扫描bean,它依据在xml文件中指定的包名和类中标记的component系列注解。
2.实例
建立spring_03_autoscan项目,内容基本和前面两个项目一样,只是在要纳入spring管理
的类前增加了component这样的注解。
Beans.xml的配置如下:
xmlversion="1.0"encoding="UTF-8"?
>
xmlns:
xsi=""
xmlns:
context=""
xsi:
schemaLocation="
"
>
component-scanbase-package="com.asm.service"/>
component-scanbase-package="com.asm.dao.impl"/>
说明:
以上的配置会自动管理service包和impl包及它们子包下的带有component标记的
类,上面两行配置代码等价于
component-scanbase-package="com.asm"/>
下面以UserServiceBean为例进行说明,代码如下:
packagecom.asm.service;
@Service("usb")@Scope("singleton")
publicclassUserServiceBean{
@Resource(name="userDaoImpl")
privateUserDaouserDao;
privateUserDaouserDao2;
@Autowired(required=true)
@Qualifier("userDaoImpl")
privateUserDaouserDao3;
@Resource
publicvoidsetUserDao2(UserDaouserDao2){
this.userDao2=userDao2;
}
publicUserServiceBean(){
}
@PostConstruct
publicvoidinit(){
System.out.println("initmethodiscalled");
}
publicvoidtest(){
System.out.println("********************************");
userDao.save();
userDao2.save();
System.out.println(userDao3);
//userDao3.save();
System.out.println("********************************");
}
}
说明:
如果使用Service这些注解时不指定名称,这些实例bean的名称就是类名(但首字母
小写),也可以指定实例bean的名字,比如这里指定其名字为“usb”,scope注解配置了bean
的作用范围,PostConstruct注解指定了bean的init方法。
关于其它的一些注解配置参文
档(3.11-3.12)。
它的junit测试代码如下:
publicclassAutoScanTest{
@Test
publicvoidbase(){
ApplicationContextctx=new
ClassPathXmlApplicationContext("beans.xml");
UserServiceBeanudb=(UserServiceBean)ctx.getBean("usb");
udb.test();
}
}
小结使用自动扫描管理的核心:
配置扫描的包、类前的component标记、了解常用注解。
五、AOP技术
1.引出问题
建立spring_04_aop项目,在该项目下有一个UserDao接口,代码如下:
packagecom.asm.dao;
publicinterfaceUserDao{
voidsave();
voidupdate();
}
该接口的实现类UseDaoImp,代码如下:
packagecom.asm.dao.impl;
importcom.asm.dao.UserDao;
publicclassUserDaoImpimplementsUserDao{
privateStringusername;
publicUserDaoImp(){
}
publicUserDaoImp(Stringusername){
this.username=username;
}
publicStringgetUsername(){
returnusername;
}
@Override
publicvoidsave(){
System.out.println("savemethodiscalled:
"+username);
}
@Override
publicvoidupdate(){
System.out.println("updatemethodiscalled"+username);
}
}
需求如下:
如果实现类的username!
=null,才可以调用save与update方法,为null则不
能调用。
当然要解决此问题,可以在save与update方法内部进行判断,但是如果在方法内
部进行判断,代码则失去了灵活性,如果以后的需求改变,比如变成username.equals时,
则又要在update/save方法中重新进行一次判断。
如果save/update这样的方法很多,这样
就会很麻烦。
其实要解决此问题,可以通过动态代理技术实现。
这里的需求其实就是根据要
求来拦截一些业务方法,这种编程问题称之为横切性关注点。
代理的目标对象必须实现了一个接口---横切关注点
2.动态代理实现[JDK]
建立代理工厂ProxyFactory,代码如下:
packagecom.asm.dao.impl.factory;
publicclassProxyFactoryimplementsInvocationHandler{
privateObjecttarget;
publicObjectcre