初识Spring
写在前面
spring是一站式开发框架,是企业级应用的方案,可以大大简化java开发,甚至有人说,java编程是面向spring的,可见spring的应用十分的广泛。本篇我们就来学习总结下spring如何简化了java开发?它的一些核心技术点是什么?
首先它如何简化了java开发呢?
1.spring是基于POJO轻量级和最小侵入式开发
其实侵入式就是要实现特定的接口,继承特定的类才能增强功能,而spring在对现有的类结构没有影响的情况下,就能够增强JavaBean的功能,所以Spring是非侵入式框架。
2. spring通过依赖注入和面向接口实现松耦合
所谓松耦合就是两个类之间不存在强的依赖关系,如service层要引入dao层的类,不需要用new关键字来创建对象。spring通过控制反转技术(IOC)来实现松耦合,更加的灵活和强大。
3.spring是基于切面和惯例进行声明式编程
面向切面编程就是我们常说的AOP了,其实java中的动态代理就是AOP,AOP思想就是,在执行某些代码前面,横切一刀,执行另外的代码。后面用案例来说明。
4.spring通过面向切面编程等减少了 很多重复代码。
其实通过上面的介绍,我们就已经知道了Spring的核心技术点的一部分,即IOC(控制反转)、AOP(面向切面编程),其实spring不仅仅只有这些,它主要有六大模块,如下:
Spring Core spring的核心功能: IOC容器, 解决对象创建及依赖关系
Spring Web Spring对web模块的支持。可以与struts整合,让struts的action创建交给spring;支持spring mvc模式
Spring DAO Spring 对jdbc操作的支持 【JdbcTemplate模板工具类】
Spring ORM spring对orm的支持:既可以与hibernate整合,【session】;也可以使用spring的对hibernate操作的封装
Spring AOP 切面编程SpringEE spring 对javaEE其他模块的支持。
下面我们就来学习Spring的核心功能,Spring Core模块的相关知识。
上面提到了 Spring Core提供了IOC容器,那么它主要有哪些类型呢?
Spring容器不单单只有一个,可以归为两种类型
1. Bean工厂,BeanFactory【功能简单】
可通过Resource获取BeanFactory,第一步加载Spring配置文件;第二步通过XmlBeanFactory+配置文件来创建IOC容器。代码如下:
//加载Spring的资源文件
Resource resource = new ClassPathResource("applicationContext.xml");
//创建IOC容器对象【IOC容器=工厂类+applicationContext.xml】
BeanFactory beanFactory = new XmlBeanFactory(resource);
2. 应用上下文,ApplicationContext【功能强大,一般我们使用这个】
可通过类路径下XML获取ApplicationContext,直接通过ClassPathXmlApplicationContext对象来获取:
// 得到IOC容器对象
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println(ac);
上面我们获取到了IOC容器,那么我们如何来获取对象呢?总的来说SPring可使用了三种获取对象的方式,如下:
1.使用XML文件配置
2.使用注解来配置
3.使用JavaConfig来配置
首先我们来看下XML文件配置的方式,上面我们已经获取了容器,获取对象时我们只需要在applicationContext.xml文件中配置对应的信息就行了,如下代码:
<!--
使用bean节点来创建对象
id属性标识着对象
name属性代表着要创建对象的类全名
-->
<bean id="user" class="User"/>
当然啦上面这种使用无参的构造方法,其实创建对象时我们还会使用多种创建方式,如有参构造、工厂创建(还要分静态和非静态)。
有参构造的XML配置方式如下:
<bean id="user" class="User">
<!--通过constructor这个节点来指定构造函数的参数类型、名称、第几个-->
<constructor-arg index="0" name="id" type="java.lang.String" value="1"></constructor-arg>
<constructor-arg index="1" name="username" type="java.lang.String" value="jbzhang"></constructor-arg>
</bean>
需要说明的事如果在constructor上构造函数的值是一个对象,而不是一个普通类型的值,如果是引用数据类型,我们就需要用到ref属性了,而不是value属性
比如说:我在User对象上维护了Emp对象的值,想要在构造函数中初始化它。因此,就需要用到ref属性了。如下代码:
<bean id="emp" class="Emp"></bean>
<bean id="user" class="User" >
<!--通过constructor这个节点来指定构造函数的参数类型、名称、第几个-->
<constructor-arg index="0" name="id" type="java.lang.String" value="1"></constructor-arg>
<constructor-arg index="1" name="username" type="java.lang.String" ref="emp"></constructor-arg>
</bean>
如果是工厂静态方法构造对象时,XML配置代码如下:
<!--工厂静态方法创建对象,直接使用class指向静态类,指定静态方法就行了-->
<bean id="user" class="Factory" factory-method="getBean" >
</bean>
如果是工厂非静态方法构造对象时,XML配置代码如下:
<!--首先创建工厂对象-->
<bean id="factory" class="Factory"/>
<!--指定工厂对象和工厂方法-->
<bean id="user" class="User" factory-bean="factory" factory-method="getBean"/>
除此外还有c名称空间的概念,
我们在使用XML配置创建Bean的时候,如果该Bean有构造器,那么我们使用这个节点来对构造器的参数进行赋值…
未免有点太长了,为了简化配置,Spring来提供了c名称空间…要想c名称空间是需要导入xmlns:c="http://www.springframework.org/schema/c"的。示例代码如下:
<bean id="userService" class="bb.UserService" c:userDao-ref="">
</bean>
下面我们来看下使用注解如何获取对象,注解的作用主要是把对象添加到IOC容器中,处理依赖关系,使用的步骤如下:
1先引入context名称空间 xmlns:context=“http://www.springframework.org/schema/context”
2 开启注解扫描器
<context:component-scan base-package=""></context:component-scan>
第二种方法:也可以通过自定义扫描类以@CompoentScan修饰来扫描IOC容器的bean对象。。如下代码:
//表明该类是配置类
@Configuration
//启动扫描器,扫描bb包下的
//也可以指定多个基础包
//也可以指定类型
@ComponentScan("bb")
public class AnnotationScan {
}
下面是一些创建对象以及处理对象依赖关系相关的注解:
@ComponentScan扫描器
@Configuration表明该类是配置类
@Component 指定把一个对象加入IOC容器—>@Name也可以实现相同的效果【一般少用】
@Repository 作用同@Component; 在持久层使用
@Service 作用同@Component; 在业务逻辑层使用
@Controller 作用同@Component; 在控制层使用
@Resource 依赖关系
如果@Resource不指定值,那么就根据类型来找,相同的类型在IOC容器中不能有两个;
如果@Resource指定了值,那么就根据名字来找。
使用注解方式的示例代码如下:
Dao层:
import org.springframework.stereotype.Repository;
//把对象添加到容器中,首字母会小写
@Repository
public class EmpDao {
public void addEmp() {
System.out.println("添加部门");
}
}
Service层
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
//把EmpService对象添加到IOC容器中,首字母会小写
@Service
public class EmpService {
//如果@Resource不指定值,那么就根据类型来找--->EmpDao....当然了,IOC容器不能有两个EmpDao类型的对象
//@Resource
//如果指定了值,那么Spring就在IOC容器找有没有id为empDao的对象。
@Resource(name = "empDao")
private EmpDao empDao;
public void addEmp() {
empDao.addEmp();
}
}
Controller层:
import org.springframework.stereotype.Controller;
import javax.annotation.Resource;
//把对象添加到IOC容器中,首字母会小写
@Controller
public class EmpAction {
@Resource(name = "empService")
private EmpService empService;
public String execute() {
empService.addEmp();
return null;
}
}
测试类:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test{
public static void main(String[] args) {
// 创建容器对象
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
EmpAction empAction = (EmpAction) ac.getBean("empAction");
userAction.execute();
}
}
3.Java API 注册方式
使用java配置类主要经过以下两个步骤:
1.编写一个java类,使用@Configuration修饰该类
2.被@Configuration修饰的类就是配置类。
示例代码如下:
@org.springframework.context.annotation.Configuration
public class Configuration {
@Bean
public EmpDao empDao() {
EmpDao empDao = new EmpDao();
System.out.println("我是在configuration中的"+empDao);
return empDao;
}
}
下面简单学习下Bean 的作用域,Bean 的作用域一共有 5 个。
(1)singleton 作用域:表示在 Spring 容器中只有一个 Bean 实例,以单例的形式存在,是默认的 Bean 作用域。
配置方式,缺省即可,XML 的配置方式如下:
<bean class="..."></bean>
(2)prototype 作用域:原型作用域,每次调用 Bean 时都会创建一个新实例,也就是说每次调用 getBean() 方法时,相当于执行了 new Bean()。
XML 的配置方式如下:
<bean class="..." scope="prototype"></bean>
(3)request 作用域:每次 Http 请求时都会创建一个新的 Bean,该作用域仅适应于 WebApplicationContext 环境。
XML 的配置方式如下:
<bean class="..." scope="request"></bean>
Java 注解的配置方式如下:
@Scope(WebApplicationContext.SCOPE_REQUEST)
或是:
@RequestScope(WebApplicationContext.SCOPE_REQUEST)
(4)session 作用域:同一个 Http Session 共享一个 Bean 对象,不同的 Session 拥有不同的 Bean 对象,仅适用于 WebApplicationContext 环境。
XML 的配置方式如下:
<bean class="..." scope="session"></bean>
Java 注解的配置方式如下:
@Scope(WebApplicationContext.SCOPE_SESSION)
或是:
@RequestScope(WebApplicationContext.SCOPE_SESSION)
(5)application 作用域:全局的 Web 作用域,类似于 Servlet 中的 Application。
XML 的配置方式如下:
<bean class="..." scope="application"></bean>
Java 注解的配置方式如下:
@Scope(WebApplicationContext.SCOPE_APPLICATION)
@RequestScope(WebApplicationContext.SCOPE_APPLICATION)
其他的关于bean对象创建的细节总结如下:
1. 对象创建: 单例/多例
scope=“singleton”, 默认值, 即 默认是单例 【service/dao/工具类】
scope=“prototype”, 多例; 【Action对象】
2 什么时候创建?
scope=“prototype” 在用到对象的时候,才创建对象。
scope=“singleton” 在启动(容器初始化之前), 就已经创建了bean,且整个应用只有一个。
3 是否延迟创建
lazy-init=“false” 默认为false, 不延迟创建,即在启动时候就创建对象
lazy-init=“true” 延迟初始化, 在用到对象的时候才创建对象
(只对单例有效)
4 创建对象之后,初始化/销毁
init-method=“init_user” 【对应对象的init_user方法,在对象创建之后执行 】
destroy-method=“destroy_user” 【在调用容器对象的destroy方法时候执行,(容器用实现类)】