Spring 基础与应用
一、什么是Spring?
Spring是分层的JavaSE/EE full-stack 轻量级开源框架,以IoC(Inverse of Control 控制反转)和AOP(Aspect Oriented Programming 面向切面编程)为内核,使用基本的JavaBean来完成以前只可能由EJB完成的工作,取代了EJB的臃肿、低效的开发模式。
在实际开发中,通常服务器端在采用三层体系架构,分别为表示层(Web)、业务逻辑层(Service)、持久层(Dao), Spring对每一层都提供了技术支持。
二、Spring的优点
Spring具有简单、可测试和松耦合等特点。Spring不仅可以用于服务器端开发,也可以应用于任何Java应用的开发中。
- 方便解耦、简化开发
- 支持AOP 支持声明式事务处理
- 方便程序测试
- 方便集成各种优秀框架
- 降低Java EE API的使用难度
- 非侵入式设计
三、Spring的体系结构
Spring框架采用的是分层架构,它一系列的功能要素被分成20个模块。
四、Spring的核心容器
Spring容器会负责控制程序之间的关系,而不是由程序代码直接控制。Spring为我们提供了两种核心容器,分别为BeanFactory和ApplicationContext
1、BeanFactory
BeanFactory提供了实例化对象和拿对象的功能;
创建BeanFactory实例时,需要提供Spring所管理容器的详细配置信息,这些信息通常采用XML文件形式来管理,其加载配置信息的语法如下:
BeanFactory beanFactory = new XmlBeanFactory(new FileSystemResource("xml文件路径"));
2、ApplicationContext
ApplicationContext是BeanFactory的子接口,是另一种常用的Spring核心容器。应用上下文,继承BeanFactory接口,它是Spring的一各更高级的容器,提供了更多的有用的功能
- 国际化(MessageSource)
- 访问资源,如URL和文件(ResourceLoader)
- 载入多个(有继承关系)上下文 ,使得每一个上下文都专注于一个特定的层次,比如应用的web层
- 消息发送、响应机制(ApplicationEventPublisher)
- AOP(拦截器)
创建ApplicationContext接口实例,通常采用两种方法,具体如下:
1.通过ClassPathXmlApplicationContext创建
ClassPathXmlApplicationContext会从类路径classPath中寻找指定的XML配置文件,找到并装载完成ApplicationContext的实例化工作
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(String configLocation);
2.通过FileSystemXmlApplicationContext创建
FileSystemXmlApplicationContext会从指定的文件系统路径(绝对路径)中寻找指定的XML配置文件,找到并装载完成ApplicationContext的实例化工作
ApplicationContext applicationContext = new FileSystemXmlApplicationContext(String configLocation);
3.通过ContextLoaderListener创建
在Java项目中,会通过ClassPathXmlApplicationContext类来实例化ApplicationContext容器。而在Web项目中,ApplicationContext容器的实例化工作会交由Web服务器来完成。
Web服务器实例化ApplicationContext容器时,通常会使用ContextLoaderListener来实现,此种方式只需要在web.xml中添加如下代码:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:spring/applicationContext.xml
</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
BeanFactory 与 ApplicationContext装载Bean的区别
BeanFactory:
BeanFactory在启动的时候不会去实例化Bean,中有从容器中拿Bean的时候才会去实例化;
应用启动的时候占用资源很少;对资源要求较高的应用,比较有优势;
ApplicationContext:
ApplicationContext在启动的时候就把所有的Bean全部实例化了。它还可以为Bean配置lazy-init=true来让Bean延迟实例化;
- 所有的Bean在启动的时候都加载,系统运行的速度快;
- 在启动的时候所有的Bean都加载了,我们就能在系统启动的时候,尽早的发现系统中的配置问题
- 建议web应用,在启动的时候就把所有的Bean都加载了。(把费时的操作放到系统启动中完成)
3.获取Bean的实例的两种方法
1.Object getBean(String name);
根据容器中Bean的id或name来获取指定的Bean,获取之后需要进行强制类型转换。
2. T getBean(Class requiredType);
根据类的类型来获取Bean的实例。由于此方法为泛型方法,因此在获取Bean之后不需要进行强制类型转换。
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(String configLocation);
//applicationContext.getBean("bean的Id");
applicationContext.getBean(xxxBean.class);
五、依赖注入
1.依赖注入的概念
DI的全称是Dependency Injection,中文称之为依赖注入。它与控制反转(IoC)的含义相同,只不过这两个称呼是从两个角度描述的同一个概念。在Spring的源码中有讲到IoC is also known as dependency injection (DI);【IOC也被称为依赖注入】所以IOC和DI本质上是同一个概念。
依赖的概念:假如A类中有一个B类的属性,那么A类就依赖了B类
注入的概念:容器将被依赖的对象注入到依赖的对象的过程
1.IoC
在使用Spring框架之后,对象的实例不再由调用者来创建,而是由Spring容器来创建,Spring容器会负责控制程序之间的关系,而不是由调用者的程序代码直接控制。这样,控制权由应用代码转移到了Spring容器,控制权发生了反转,这就是控制反转。
2.DI
从Spring容器的角度来看,Spring容器负责将被依赖对象赋值给调用者的成员变量,这相当于为调用者注入了它依赖的实例,这就是Spring的依赖注入。
2.Spring依赖注入的三种方式
在Spring容器中为一个bean配置依赖注入有三种方式:
· 使用属性的setter方法注入
· 使用构造器注入;
· 使用Filed注入(用于注解方式)
1.使用属性的setter方法注入
使用setter方法注入时,需要给属性定义set方法;
public class User{
private String name;
private int age;
public void setName(String name){
this.name = name;
}
}
<bean id="User" class="com.wwx.User">
<property name="name" value="wuwei"/>
<property name="age" value="18"/>
……
</bean>
注意:在User中没有定义构造器,则JVM自动为其生成一个默认的构造函数。若在User中定义了有参的构造函数,则需定义一个无参的构造函数,否则注入时会抛出异常。
2.使用构造器注入
构造函数注入是除属性注入之外的另一种常用的注入方式,它保证一些必要的属性在Bean实例化时就得到设置(construct是bean生命周期的第一步,实例化bean),并且确保了Bean实例在实例化后就可以使用。
在配置文件中配置该类的bean,并配置构造器,在配置构造器中用到了节点,该节点有四个属性:
· index是索引,指定注入的属性,从0开始;
· type是指该属性所对应的类型,如UserDao对应的是com.wwx.dao.UserDao;
· ref 是指引用的依赖对象;
· value 当注入的不是依赖对象,而是基本数据类型时,就用value;
public class UserServiceImpl interface UserService{
private UserDao userDao;
private String userName;
//提供构造方法
public UserServiceImpl(){}
public UserServiceImpl (UserDao userDao,String userName){
this.userDao = userDao;
this.userName = userName;
}
}
<!-- 利用构造器配置依赖注入 -->
<bean id="userDao" class="com.wwx.dao.UserDao"></bean>
<bean id="UserService" class="com.wwx.service.impl.UserServiceImpl ">
<constructor-arg index="0" type="com.wwx.dao.UserDao"ref="userDao"></constructor-arg>
<constructor-arg index="1" value="Spring学习"></constructor-arg>
</bean>
3.使用Field注入(用注解注入)
装配方式有4种:name、type、constructor、autodetect
具体选择哪一种装配方式,需要配置标签的autowire属性,如果没有配置,默认是byName类型,就是会根据属性的名字来进行自动装配。
1)name就是会将与属性的名字一样的bean进行装配。
2)type就是将同属性一样类型的bean进行装配。
3)constructor就是通过构造器来将类型与参数相同的bean进行装配。
4)autodetect是constructor与byType的组合,会先进行constructor,如果不成功,再进行byType。
使用注解方式注入的具体步骤:
(1)在Spring容器的配置文件applicationContext.Xml文件中配置以下内容
<?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:context="http://www.springframework.org/schema/context"
xmlns:p="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/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
">
注意:只有配置了红色部分的代码才可以引入注解的命名空间,否则报错。 以上的配置隐式的注册了多个对注释进行解析的处理器:AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、PersistenceAnnotationBeanPostProcessor等。
(2)在配置文件中打开context:annotation-config节点
<beans>
<context:annotation-config></context:annotation-config>
</beans>
(3)在配置文件中配置bean
<bean id="userDao" class="com.wwx.dao.impl.UserDao"></bean>
<bean id="userService" class="com.wwx.dao.impl.UserServiceImpl"></bean>
(4)给声明的依赖对象加注解
public class UserServiceImpl interface UserService{
@Autowired
@Qualifier("userDao")
//@Resource("userDao")
private UserDao userDao;
public void test(){
}
}
使用@Autowired或@Resource区别是:@Autowired默认按类型装配,@Resource默认按名称装配,当找不到与名称匹配的bean时,才会按类型装配。
@Autowired和@Qualifier("…")可以同时使用,利用@Qualifier("…")指定特定的被依赖对象的名称。
补充:常用的注入注解有@Autowired,@Qualifier,@Named,@Resource,@Inject;(关于@Inject自定义注解会在后面的文章详细讲)
六、自动装配
Spring容器可以自动装配协作bean之间的关系。
自动装配具有以下优点:
(1)自动装配可以大大减少指定属性或构造函数参数的需要。
(2)随着对象的发展,自动装配可以更新配置。例如,如果您需要向类中添加依赖项,则无需修改配置即可自动满足该依赖项。
因此,自动装配在开发过程中特别有用,而不必担心在代码库变得更稳定时切换到显式接线的选择。
自动装配分为以下4种模式:(4种自动装配模型)
模式 | 说明 |
no | (默认)无自动装配。Bean引用必须由ref元素定义。对于较大的部署,建议不要更改默认设置,因为明确指定协作者可以提供更好的控制和清晰度。在某种程度上,它记录了系统的结构。 |
byName | 按属性名称自动布线。Spring寻找与需要自动装配的属性同名的bean。例如,如果一个bean定义被设置为按名称自动装配并且包含一个master属性(即它具有一个 setMaster(…)方法),那么Spring将查找一个名为的bean定义,master并使用它来设置该属性。 |
byType | 如果容器中恰好存在一个属性类型的bean,则使该属性自动连接。如果存在多个错误,则会引发致命异常,这表明您可能无法byType对该bean 使用自动装配。如果没有匹配的bean,则什么都不会发生(未设置该属性)。 |
constructor | 类似于byType但适用于构造函数参数。如果容器中不存在构造函数参数类型的一个bean,则将引发致命错误。 |
接下来准备继续更新Spring其他知识的文章(包括源码详解)~~