在学习Spring之前,我们首先要了解,spring究竟是什么东西,我们为什么要学习Spring?
一、Spring是什么?
1、Spring是一个开源的框架,它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架;Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。 Spring的核心是控制反转(IoC)和面向切面(AOP)。简单来说,Spring是一个分层的JavaSE/EE full-stack(一站式) 轻量级开源框架。
2、Spring为简化企业级应用开发而生,使用spring可以使简单的javaBean实现以前只有EJB才能实现的功能。
3、Spring是一个IOC(DI)、AOP容器框架。(关于IOC(DI)、AOP是什么会在接下来的内容中讲到)
4、Spring是一个一站式的开发框架。(所谓一站式,通俗的说就是能把项目创建需要的三个阶段全部包括进来)
二、为什么要学习Spring?
1、 方便解耦,简化开发。Spring就像是一个大工厂一样,把所有的对象创建和依赖关系维护,交给Spring管理.
2、AOP编程支持。Spring提供面向切面的编程,可以方便的对程序实施拦截和监控的功能。
3、声明式事务的支持。只需要通过配置就能完成对事务的管理,而无需手动编程。
4、方便程序测试。Spring对Juit4支持,通过注解就能方便的测试Spring的程序。
5、方便集成各种优秀的框架。Spring不排斥各种开源框架,提供对各种框架(如:Struts2、Hibernate、MyBatis、Quartz、shiro等)的支持。
6、降低了JavaEE API的使用难度。Spring对JavaEE中非常难用的一些API(JDBC、JavaMail、远程调用等)都提供了封装,使得这些API的使用难度大大降低。
三、Spring容器的概念及三种创建方式
1、概念。核心容器提供 Spring 框架的基本功能(Spring Core)。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转(IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。
2、三种创建方式。
第一种 XmlBeanFactory来获取容器类(已经过期,不建议使用)
a、创建核心配置文件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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
</beans>
b、创建测试类获取容器
@Test
public void testName() throws Exception {
//使用XmlBeanFactory来获取容器,需要传入一个配置文件的路径
XmlBeanFactory BeanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
Class<? extends XmlBeanFactory> class1 = BeanFactory.getClass();
System.out.println(class1);
}
第二种 ClassPathXmlApplicationContext获取容器类(最常用)
a 核心配置文件不变
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
</beans>
b、在测试类中获取容器(从类路径中获取)
@Test
public void testName2() throws Exception {
ApplicationContext ApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Class<? extends ApplicationContext> class1 = ApplicationContext.getClass();
System.out.println(class1);
}
第三种方式FileSystemXmlApplicationContext
a 核心配置文件不变
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
</beans>
b、在测试类中获取容器(从文件系统中获取)
@Test
public void testName3() throws Exception {
ApplicationContext ApplicationContext = new FileSystemXmlApplicationContext("D:\\demoo\\worespace2018\\spring0701\\src\\main\\resources\\applicationContext.xml");
Class<? extends ApplicationContext> class1 = ApplicationContext.getClass();
System.out.println(class1);
}
四、spring的第一大特性:IOC
1、什么是IOC?inversion of control 控制反转
什么是控制反转:说白了就是将创建对象的过程或者说创建对象的权限交给了spring框架来帮我们处理,我们再不用通过new的方式来创建Javabean对象,这个过程就叫做控制反转。
2、DI。dependency injection 依赖注入: 就是组件以一些预先定义好的方式(例如: setter 方法)接受来自如容器的资源注入。说白了就是使用spring框架为我们的JavaBean的属性赋值的过程。
3、Javabean在容器中创建的三种方式
第一种方式。使用默认构造器
a、创建UserBean
public class UserBean {
private String info;
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
public void show(){
System.out.println("show方法被调用..........."+info);
}
}
b、在核心文件中配置UserBean
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="userbaen" class="cn.itcast.dao.UserBean">
<property name="info" value="测试赋值" />
</bean>
</beans>
c、在测试类中测试
@Test
public void testName4() throws Exception {
ApplicationContext ApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
//两个获取对象方式都可以
UserBean bean = (UserBean) ApplicationContext.getBean("userbaen");
UserBean bean2 = ApplicationContext.getBean(UserBean.class);
bean.show();
bean2.show();
}
第二种方式、使用静态工厂
调用静态工厂方法创建Bean是将对象创建的过程封装到静态方法中。当客户端需要对象时,只需要简单地调用静态方法,而不用关心创建对象的细节(往往使用工厂方法就是为了应对创建对象比较复杂的情况)。
a、创建JavaBean
public class Car {
private String brand;//品牌
private Integer price;//价格
//添加无参,全参构造
//添加GET、SET方法
}
b、创建静态工厂StaticCarFactoy
public class StaticCarFactoy {
private static Map<String, Car> cars=new HashMap<>();
static{
cars.put("audi", new Car("audi", 300000));
cars.put("bmw", new Car("bmw", 500000));
}
public static Car getCar(String brand){
return cars.get(brand);
}
}
c、在核心配置文件中配置Javabean对象
<bean id="car1" class="cn.itcast.dao.StaticCarFactoy" factory-method="getCar" >
<constructor-arg value="audi" ></constructor-arg>
</bean>
d、测试
@Test
public void testName5() throws Exception {
ApplicationContext ApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Car car = (Car) ApplicationContext.getBean("car1");
System.out.println(car.getPrice());
}
第三种方式,使用实例工厂
将对象的创建过程封装到另外一个对象实例的方法里。当客户端需要请求对象时,只需要简单的调用该实例方法而不需要关心对象的创建细节(往往使用工厂方法就是为了应对创建对象比较复杂的情况)。
a、创建JavaBean
public class Car {
private String brand;//品牌
private Integer price;//价格
//添加无参,全参构造
//添加GET、SET方法
}
b、创建实例工厂InstanceCarFactory
public class InstanceCarFactory {
private Map<String, Car> cars=null;
public InstanceCarFactory(){
cars=new HashMap<>();
cars.put("audi", new Car("audi", 300000));
cars.put("bmw", new Car("bmw", 500000));
}
public Car getCar(String brand){
return cars.get(brand);
}
}
c、在核心配置文件中配置Javabean对象
<bean id="instanceCarFactory" class="cn.itcast.dao.InstanceCarFactory" >
</bean>
<bean id="car2" factory-bean="instanceCarFactory" factory-method="getCar" >
<constructor-arg value="bmw" ></constructor-arg>
</bean>
d、测试
@Test
public void testName6() throws Exception {
ApplicationContext ApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Car car = (Car) ApplicationContext.getBean("car2");
System.out.println(car.getPrice());
}
4、bean作用域
在Spring中,可以在< bean>元素的scope属性里设置Bean的作用域。默认有四种取值:Singleton、prototype、request、session
singleton:默认值,容器初始化是创建bean实例,在整个容器的生命周期内只创建这一个bean,单例的。
prototype:原型的,容器初始化时不创建bean的实例,而在每次请求时都创建一个新的Bean实例,并返回。
5、Bean的生命周期
通过构造器或工厂方法创建Bean实例,为Bean的属性设置值和对其他Bean的引用,调用Bean的初始化方法,Bean可以使用了,当容器关闭时,调用Bean的销毁方法
五、Spring的属性注入之DI
第一种方式、set方法注入
通过setter方法注入Bean的属性值或依赖的对象。对应的实体类中一定要有getter和setter方法,如果写了带参的构造器, 一定要有空参的构造器,因为容器用此方法创建对象时会调用空参的构造器。
1、创建Javabean
public class Person {
private String username;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
2、在核心文件中配置Bean
<!-- set方式注入类属性 -->
<bean id="person1" class="cn.itcast.dao.Person">
<property name="username" value="小泽"></property>
</bean>
3、测试
@Test
public void testName7() throws Exception {
ApplicationContext ApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person = (Person) ApplicationContext.getBean("person1");
System.out.println(person.getUsername());
}
第二种方式、构造器注入
通过构造方法注入Bean 的属性值或依赖的对象。
1、创建Javabean,生成有参构造
public class Person {
private String username;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
//有参构造
public Person(String username) {
super();
this.username = username;
}
}
2、在核心文件中配置Bean
<!-- 有参构造注入 -->
<bean id="person2" class="cn.itcast.dao.Person">
<constructor-arg name="username" value="小苍" ></constructor-arg>
</bean>
3、测试
@Test
public void testName8() throws Exception {
ApplicationContext ApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person = (Person) ApplicationContext.getBean("person2");
System.out.println(person.getUsername());
}
第三种方式、p命名空间和c命名空间
第四种、集合属性的赋值
六、Spring与Web整合
1、为什么需要整合?
我们所做的项目都是web项目,在我们的web项目中需要用到spring容器中的bean对象,Spring容器不需要重复创建,一个web项目只创建一个spring容器就够了,整合web是后面整合springmvc的基础。
2、整合的步骤
2.1、 导入spring-web和servlet的jar包
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
2.2、配置监听器,监听web项目的启动
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
2.3、创建servlet,获取Spring容器
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext servletContext = getServletContext();
//获取容器
WebApplicationContext webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
//获取容器对象
Person person = (Person) webApplicationContext.getBean("person2");
System.out.println(person+"111");
response.getWriter().append("Served at: ").append(request.getContextPath());
}
2.4 在pom.xml中启动Tomcat软件看效果
运行tomcat7:run
七、spring容器基于注解方式的开发
1、为什么要引入注解方式?
1.1、如果所有的配置在XML文件中,xml文件会十分的庞大;如果按需求分开XML文件,那么XMl文件又会十分的多。不利于维护和管理。
1.2、在开放中来回的切换.java和.xml。影响开发的效率
1.3、引入注解后,一方面能减少XML文件的配置,另外一方面也有利于程序的维护与开发。
2、注解开发的步骤
2.1、导入JAR包
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
2.2 配置核心文件
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd">
<!-- 开启注解扫描 -->
<context:component-scan base-package="cn.itcast.dao"></context:component-scan>
</beans>
2.3给类添加注解
@Repository//标记这个类会在容器中创建对象
public class Cardao {
public void insertcar(String car){
System.out.println("Cardao=======>"+car);
}
@Service//在容器中添加对象
public class CarService {
@Autowired//向容器中请求拿这个对象
private Cardao cardao;
public void addcar(String car){
this.cardao.insertcar(car);
}
}
2.4spring整合Junit4进行测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext4.xml")
public class Junit4 {
@Autowired
private CarService carService;
@Test
public void testName() throws Exception {
carService.addcar("宝马");
}
}