Spring基础入门1 - IoC容器

1. Spring简介

Spring是一个开源, 一站式的, 轻量级的Java企业应用开发框架。

  1. Spring框架是一个企业应用开发框架, 简单来说就是开发服务器端应用的框架;
  2. Spring是轻量级的框架, 与传统的EJB类似, Spring框架也是采用容器来管理应用对象(Bean), 但是从大小与开销两方面而言Spring都是轻量的, 完整的Spring框架可以在一个大小只有1MB多的JAR文件里发布;
  3. Spring是一站式(full-stack)的框架, Spring非常全面, 无缝整合了各种优秀开源框架(如Struts, Hibernate, Hessian, Quartz), 成为Spring的开箱即用的功能模块, 对用开发者来说, 你只需要一个Spring Framework;
  4. Spring是一个开源的框架(https://github.com/spring-projects/), 采用的是非常宽松的Apache-2.0 License许可协议, 意味则你可以几乎不受限制的使用她,包括用于商业软件的开发;

“Rod Johnson在2002年编著的《Expert one on one J2EE design and development》一书中,对Java EE 系统框架臃肿、低效、脱离现实的种种现状提出了质疑,并积极寻求探索革新之道。以此书为指导思想,他编写了interface21框架,这是一个力图冲破J2EE传统开发的困境,从实际需求出发,着眼于轻便、灵巧,易于开发、测试和部署的轻量级开发框架。Spring框架即以interface21框架为基础,经过重新设计,并不断丰富其内涵,于2004年3月24日,发布了1.0正式版。同年他又推出了一部堪称经典的力作《Expert one-on-one J2EE Development without EJB》,该书在Java世界掀起了轩然大波,不断改变着Java开发者程序设计和开发的思考方式。在该书中,作者根据自己多年丰富的实践经验,对EJB的各种笨重臃肿的结构进行了逐一的分析和否定,并分别以简洁实用的方式替换之。至此一战功成,Rod Johnson成为一个改变Java世界的大师级人物。”

引用自"https://www.cnblogs.com/ysocean/p/7466191.html", 介绍非常详细。

Spring框架的核心是控制反转(IoC)和面向切面(AOP), 这也是Spring框架上层Spring各模块之间灵活可扩展和松耦合的基石。

2. Spring容器/Bean

Spring框架的一个主要特性就是IoC(Inversion of Control,控制反转)容器, 它通过DI(Dependency Injection)来实现控制反转。在Spring框架中, 我们可以通过IoC容器来管理(Java)对象, 而不是通过代码。IoC容器负责创建对象,把它们连接在一起,配置它们,并管理它们的整个生命周期从创建到销毁。通过Spring IoC容器管理的Java对象就称为Spring Bean。

在Spring框架下我们是否需要将所有的需要用到的对象都定义为Spring Bean呢? 从最佳实践上看并不需要这样。
“As per Spring documentation, in general, we should define beans for service layer objects, data access objects (DAOs), presentation objects, infrastructure objects such as Hibernate SessionFactories, JMS Queues, and so forth.”

Spring框架中Ioc容器相关的基本类包含在org.springframework.beans和org.springframework.context包下,从编码角度看, BeanFactory接口对应Spring Ioc容器, BeanFactory接口是访问Spring容器的根接口, 它定义了Spring容器的基本功能。 一个Spring容器可以看成一个实现了BeanFactory接口的实例化对象。
在这里插入图片描述
从API文档可以看到BeanFactory还有一系列的子接口(sub-interface), 继承扩展了BeanFactory接口, 包括我们常见到的ApplicationContext和WebApplicationContext接口。

"The BeanFactory interface provides an advanced configuration mechanism capable of managing any type of object. ApplicationContext is a sub-interface of BeanFactory. It adds easier integration with Spring’s AOP features; message resource handling (for use in internationalization), event publication; and application-layer specific contexts such as the WebApplicationContext for use in web applications.

In short, the BeanFactory provides the configuration framework and basic functionality, and the ApplicationContext adds more enterprise-specific functionality. The ApplicationContext is a complete superset of the BeanFactory, and is used exclusively in this chapter in descriptions of Spring’s IoC container."

Spring还提供了非常丰富的最终实现类, 应对不通的功能和应用场景。如ClassPathXmlApplicationContext,FileSystemXmlApplicationContext, AnnotationConfigApplicationContext,…

Ioc—Inversion of Control,即"控制反转 ", 并不是什么技术,而是一种设计思想。传统Java SE程序设计, 当一个对象依赖另一个对象, 我们会通过程序代码new一个对象。而IoC思想是通过一个容器来创建这些依赖对象,而不是通过编写代码。由IoC容器帮我们查找及注入依赖对象, 对象只是被动的接受依赖对象, 依赖对象的获取被反转了, 这就是控制反转。

例如, 一个对象需要访问数据库,传统模式下我们会编写代码创建数据库连接的Connection对象,假设我们是通过dbcp连接池来创建一个连接, 那么我们就使用dbcp的相关类初始化连接池, 并创建Conection传给需要的对象,这就产生了耦合,如果我们想换成hikari连接池,就需要修改代码,而如果对象创建由IoC容器控制,那么我们就可以通过配置IoC来实现我们想要的对象创建,这就实现了解耦。

概念听起来都是很抽象,先从最简单的基础开始,一步步来理解感受Spring。

3. Spring容器用法

Spring容器的主要任务就是管理Bean,而如何管理Bean则需要通过配置来告诉容器,Spring应用的基本流程是: 创建一个容器IoC实例,IoC容器实例根据配置装载配置定义的Beans,我们再通过容器获取bean,调用bean的方法。

Spring支持多种不通的方式来配置beans:

  • XML-Based Configuration;
  • Annotation-Based Configuration;
  • Java-Based Configuration;

下面基于Spring 5 + Eclipse, 写一个简单的使用例子。首先在Eclipse中创建一个"maven-archetype-quickstart"类型的maven项目,并在pom.xml中加入spring-context的依赖即可:

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-context</artifactId>
	<version>5.3.14</version>
</dependency>

3.1. XML-Based Configuration

Spring中最传统的配置Bean的方式是通过XML文件来定义。其中常用的基于XML配置的容器实现类有:

  • FileSystemXMLApplicationContext: Load an XML-based Spring configuration file from the file system or from URLs;
  • ClassPathXmlApplicationContext: Load an XML-based Spring configuration file from the file system or from URLs;
  • XmlWebApplicationContext: Load XML based configuration in a web application;

在org.littlestar.learning.packe3包下创建一个普通Hello类和Spring配置文件package3-bean-config.xml, 我们将Hello类配置成一个Spring Bean,并通过容器来获取Hello类的实例。
在这里插入图片描述

package org.littlestar.learning.package3;

public class Hello {
	private String msg;

	public Hello() {
	}
	
	public Hello(String msg) {
		this.msg = msg;
	}

	public void setMsg(String msg) {
		this.msg = msg;
	}

	public void sayHello() {
		System.out.println("Hello~ " + msg);
	}

	public void destroy() {
		System.out.println("Hello(" + msg + ") is destroyed.");
	}
}

package3-bean-config.xml:

通过<bean …>来告诉IoC容器如何装载Bean,默认情况下, Spring Bean是单例的(singleton), 也就是容器中只会创建一个对象, 不是每次用到时都去new。我们可以通过指定scope="prototype"来指定为多实例模式。

即便是默认scope=“singleton”, 同一个类我们也可以配置不同的初始化方式,创建想要的不同的bean,但是需要通过指定id属性来区分。

<?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.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">

	<bean id="helloSpring" class="org.littlestar.learning.package3.Hello">
		<property name="msg" value="Spring"></property>
	</bean>
	
	<bean id="helloJava" class="org.littlestar.learning.package3.Hello">
		<constructor-arg name="msg" type="java.lang.String" value="Java" />
	</bean>
</beans>

最后写main函数启动代码, 通过ClassPathXmlApplicationContext读取类路径下org/littlestar/learning/package3/package3-bean-config.xml配置文件,并装载定义的Bean,通过容器的getBean方法来获取Hello对象。

package org.littlestar.learning.package3;

import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App3 {

	public static void main(String[] args) {
		/ demo: XML-Based Configuration
		try (ConfigurableApplicationContext context = new ClassPathXmlApplicationContext(
				"org/littlestar/learning/package3/package3-bean-config.xml")) {
			// No qualifying bean of type 'org.littlestar.learning.package3.Hello' available: expected single matching bean but found 2: helloSpring,helloJava
			// Hello hello1 = context.getBean(Hello.class);
			Hello hello1 = context.getBean("helloSpring", Hello.class);
			hello1.sayHello();
			hello1.setMsg("Spring 5");
			Hello hello2 = context.getBean("helloSpring", Hello.class);
			hello2.sayHello();

			Hello hello3 = context.getBean("helloJava", Hello.class);
			hello3.sayHello();
		}
	}
}

执行结果:
Hello~ Spring
Hello~ Spring 5
Hello~ Java

3.2 Annotation-Based Configuration

从Spring 2.5+开始, Spring可以通过注解(Annotation)来进行Bean的配置。xml配置文件只需要配置annotation-config和component-scan, IoC容器可以自动扫描base-package包下的所有类, 并装载指定注解标注的为Bean的类。注解方式是当前最主要使用的方式。

package4-bean-config.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"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">
	<context:annotation-config />
	<context:component-scan base-package="org.littlestar.learning.package4" />
</beans>

可以通过@Component标注一个Spring管理的Bean,使用@Component注解在一个类上,即可将此类标记为Spring容器中的一个Bean。根据用途的不同, @Component还有许多的扩展注解,如: @Repository,@Service, @Controller,… 他们都是将其注解的类标注为Bean。

package org.littlestar.learning.package4;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component(value="helloSpring") // 相当于XML配置的<bean id="helloSpring" ..></bean>
public class Hello {
	@Value("Spring")
	private String msg;

	public Hello() {
	}
	
	public Hello(String msg) {
		this.msg = msg;
	}

	public void setMsg(String msg) {
		this.msg = msg;
	}

	public void sayHello() {
		System.out.println("Hello~ " + msg);
	}

	public void destroy() {
		System.out.println("Hello(" + msg + ") is destroyed.");
	}
}

也可以通过@Autowired注解来实现从容器中获取bean, 进一步简化了使用。

package org.littlestar.learning.package4;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component
public class MyHello {
	@Autowired   
	@Qualifier("helloSpring") 
	Hello hello; // 相当于Hello hello = context.getBean("helloSpring", Hello.class);
	public void sayHello() {
		hello.sayHello();
	}
}

在main方法中,启动容器:

package org.littlestar.learning.package4;

import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App4 {
	public static void main(String[] args) {
		/ demo: Annotation-Based Configuration, Spring 2.5+
		try (ConfigurableApplicationContext context = new ClassPathXmlApplicationContext(
				"org/littlestar/learning/package4/package4-bean-config.xml")) {
			Hello hello1 = context.getBean("helloSpring", Hello.class);
			hello1.sayHello();
			hello1.setMsg("Spring 5");
			Hello hello2 = context.getBean(Hello.class);
			hello2.sayHello();
			MyHello subHello = context.getBean(MyHello.class);
			subHello.sayHello();
		}
	}
}

3.3. Java-Based Configuration

从Spring 3.0+开始, 可以不使用xml配置文件,而是通过编写配置类(通过@Configuration标注的类)的方式来配置Spring beans。也可以通过@ComponentScan通过自动扫描来装载。对于复杂的Spring Bean,还可以通过@Bean注解的手动编写方法来装载Bean。

package org.littlestar.learning.package5;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration //相当于一个xml配置文件<beans></beans>
//相当于<context:annotation-config />和<context:component-scan ../>
@ComponentScan(basePackages="org.littlestar.learning.package5") 
public class AppConfig1 {
	@Bean // 相当于<bean id="defaultHello" ...></bean>
	public Hello defaultHello() {
		Hello hello = new Hello();
		hello.setMsg("Spring");
		return hello;
	}
	
	@Bean(name="helloJava") // 相当于<bean id="helloJava" ...></bean>
	public Hello helloJava() {
		Hello hello = new Hello("Java");
		return hello;
	}
}

编写一个启动类,启动容器:

package org.littlestar.learning.package5;

import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class App5 {
	public static void main(String[] args) {
		/ demo: Java-Based Configuration, Spring 3.0+
		try (ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(AppConfig1.class)){
			Hello hello1 = context.getBean("defaultHello", Hello.class);
			hello1.sayHello();
			Hello hello2 = context.getBean("helloJava", Hello.class);
			hello2.sayHello();
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值