Spring学习笔记——Bean

本文深入探讨Spring框架,从初识Spring、核心容器、入门程序到依赖注入(DI)和控制反转(IoC)的概念及实现,详细讲解Spring中Bean的配置、实例化、装配方式和生命周期,帮助读者全面理解Spring如何管理Bean。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、初识Spring框架

1、Spring框架是什么?
Spring框架是一个分层的JavaEE轻量级开源框架,它以IoC和AOP为内核,使用最基本的JavaBean来完成工作。

2、Spring的优点
1-非侵入式设计:使应用程序代码对框架的依赖最小化。
2-方便解耦、简化开发:将所有对象的创建和依赖关系的维护工作交由Spring容器管理。
3-支持AOP:将一些通用任务,如事务处理,日志记录等集中处理,提高了代码的复用性。
4-支持声明式事务处理:通过配置即可完成事务的处理。
5-方便程序的测试:集成了Junit4,使用注解完成程序的测试
6-方便集成各种优秀框架
7-降低了JavaEE API的使用难度:对一些较难使用的API,如JDBC等进行了封装。

3、Spring框架的体系结构
在这里插入图片描述主要模块介绍:
(1)Beans模块:提供了BeanFactory,是工厂模式的典型实现。
(2)Core核心模块:提供了Spring框架的基本组成部分,包括IoC和DI功能。
(3)Context模块:建立在Beans模块和Core模块的基础之上。它是访问定义和配置任何对象的媒介,其中ApplicationContext接口是上下文模块的焦点。
(4)SpEL模块:Spring3.0后新增的模块,是运行时查询和操作对象图的强大表达式语言。
(5)AOP模块:提供了面向切面编程实现,允许定义方法拦截器和切入点,将代码按照功能进行分离,以降低耦合性。
(6)AspectJ模块:提供了与AspectJ的集成功能。AspectJ是一个功能强大且成熟的面向切面编程(AOP)的框架
(7)Web模块:提供了基本的Web开发集成特性,如多文件上传功能,使用Servlet监听器初始化IoC容器,以及Web应用上下文。
(8)Servlet模块:也成为Spring-webmvc模块,它包含了Spring的MVC和REST Web Service实现的Web应用程序。
(9)JDBC模块:提供了一个JDBC的抽象层,大幅度减少了对数据库操作的编码。
(10)ORM模块:提供了对流行的对象关系映射API。
(11)Transaction模块:提供了支持对实现特殊接口,以及所有POJO类的编程和声明式的事务管理。
(12)Test模块:提供了对单元测试和集成测试的支持。

二、Spring的核心容器

Spring框架的主要功能是通过其核心容器来实现的,Spring框架提供了两种核心容器:BeanFactory和ApplicationContext。

1、BeanFactory
BeanFactory是基础的IoC容器,它提供了完整的IoC服务支持。简单的说,BeanFactory是一个管理Bean的工厂,它主要负责初始化各种Bean,并调用它们的生命周期方法。加载该容器的方法(不常用):

BeanFactory beanFactory=new XmlBeanFactory(new FileSystemResources("F:/applicationContext.xml"));

2、ApplicationContext
ApplicationContext是BeanFactory的子接口,也被称为应用上下文。不仅包含了BeanFactory的所有功能,还添加了对国际化,资源访问、事件传播等方面的支持。创建ApplicationContext接口实例通常采用两种方式:
(1)ClassPathXMLApplicationContext
ClassPathXMLApplicationContext会从类路径classpath中寻找指定的xml配置文件,找到并加载配置文件完成ApplicationContext的初始化工作。

ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");

(2)FileSystemXmlApplicationContext
FileSystemXmlApplicationContext会使用绝对路径加载配置文件。

ApplicationContext context=new FileSystemXmlApplicationContext("D:/applicationContext.xml");

在单独使用Spring框架时,可采取以上任意一种方式完成ApplicationContext的初始化工作。在web项目中,ApplicationContext容器的初始化工作会交给Web服务器来完成。Web服务器基于ContextLoaderListener来完成ApplicationContext的实例化。此种方式需要在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>

初始化容器后,可以通过以下两种方法获取容器中的bean:

根据容器中bean的id或name获取
Object getBean(String name);
根据类型获取bean的实例
<T> T getBean(Class<T> requiredType);

三、Spring框架的入门程序

1、项目结构
在这里插入图片描述
注意:Spring框架的运行依赖于commons-logging组件。

2、类定义
JavaBean:HelloSpring .java

public class HelloSpring {
	//通过Spring框架赋值
	private String text;
	
	public HelloSpring() {}
	
	public HelloSpring(String text) {
		this.text=text;
	}
	
	public void print() {
		System.out.println(text);
	}
	
	public void setText(String text) {
		this.text=text;
	}
	
	public String getText() {
		return text;
	}
}

测试类:HelloTest.java

public class HelloTest {

	public static void main(String[] args) {
		//初始化AapplicationContext容器
		ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
		//通过类型的方式获取Bean
		HelloSpring h1=context.getBean(HelloSpring.class);
		h1.print();
		//通过bean的id获取Bean
		HelloSpring h2=(HelloSpring)context.getBean("helloSpring");
		System.out.println(h2.getText());
		//判断得到的两个对象是否相同
		System.out.println("h1 == h2 :"+(h1 == h2));
	}
}

3、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">

	<!-- id:唯一指定Bean在容器中的名字 class:指定Bean的类型-->
	<bean id="helloSpring" class="com.tracker.pojo.HelloSpring">
		<!-- 调用setText()方法给属性赋值 ,注意命名规范:name属性值应该是setXXX()中的XXX-->
		<property name="text">
			<value>Hello,Spring</value>
		</property>
	</bean>
</beans>

4、控制台输出
在这里插入图片描述从上述例子中可以发现,Spring框架会自动接管配置文件中Bean的创建并为属性赋值,而不用在程序中使用new关键字主动创建Bean和管理。

四、依赖注入(DI)和控制反转(IoC)

1、概念理解
依赖注入(Dependency Injection)与控制反转(Inversion of Control)的含义相同,只不过是从两种角度描述同一个概念。
在传统方式中,一个Java对象(调用者)需要调用另一个Java对象(被调用者,即被依赖对象)时,需要使用“new 被调用者”的方式来创建对象。这种方式会导致调用者与被调用者之间的耦合度增加,不利于后期维护。
在Spring框架中,对象的实例不再由调用者来创建,而是由Spring容器来创建管理。创建对象的控制权由应用代码转移到Spring容器,控制权发生反转,这就是控制反转。
从Spring框架容器的角度来看,它负责将被依赖对象赋值给调用者的成员变量,相当于为调用者注入了其依赖实例,这就是依赖注入。
可以说,IoC是一种设计理念,DI是IoC的具体实现。

2、依赖注入的实现方式
(1)属性setter方法注入

<bean id="helloSpring" class="com.tracker.pojo.HelloSpring">
		<!-- 调用setter方法给属性赋值 -->
		<property name="text">
			<value>Hello,Spring</value>
		</property>
</bean>

(2)构造方法注入

<bean id="helloSpring" class="com.tracker.pojo.HelloSpring">
		<!-- 调用构造方法给属性赋值 -->
		<constructor-arg index="0" value="Hello,Spring!"/>
		<!--或: <constructor-arg name="text" value="Hello,Spring!"/>-->
</bean>

3、控制反转的优点
在Spring框架中,bean与bean之间的依赖关系都放在配置文件里组织,而不是写在代码里,将bean的创建和依赖注入交由Spring容器进行管理,大大降低了bean之间的耦合度,方便后期维护。

五、Spring框架中的Bean

1、Bean的配置
在Spring的配置文件中,通过<bean>标签定义一个JavaBean。其属性和子元素如下:
在这里插入图片描述注意:如果在Bean中未指定id或name属性,则Spring会将class值当做id属性使用。

2、Bean的实例化
在Spring中,实例化Bean有三种方式:
(1)方式一:构造器实例化

<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="helloSpring" class="com.tracker.pojo.HelloSpring"></bean>
</beans>

(2)方式二:静态工厂方式实例化

public class MyBeanFactory{
	public static HelloSpring createBean(){
		return new HelloSpring();
	}
}
<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">
	<!--class:指定静态工厂 factory-method:指定创建bean实例的方法-->
	<bean id="helloSpring" class="com.tracker.factory.MyBeanFactory"
		factory-method="createBean"></bean>
</beans>

(3)方式三:实例工厂方式实例化

public class MyBeanFactory{
	public  HelloSpring createBean(){
		return new HelloSpring();
	}
}
<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="myfactory" class="com.tracker.factory.MyBeanFactory"/>
	<!--factory-bean:指定工厂实例 factory-method:指定创建bean实例的方法-->
	<bean id="helloSpring" factory-bean="myfactory"	factory-method="createBean"/>
</beans>

3、Bean的装配方式
Bean的装配可以理解为依赖关系注入,Spring容器常用的三种装配方式:基于XML的装配,基于注解的装配,自动装配。
(1)基于XML的装配
基于XML的装配有两种方式:设值注入、构造注入。
设值注入要求一个Bean必须满足两个要求:1.提供一个默认的无参构造器 2.为需要注入的属性提供对应的setter方法
构造注入要求Bean必须提供有参构造器,使用<constructor-arg>标签注入。
不同类型注入方式:

	<bean id="helloSpring" class="com.tracker.pojo.HelloSpring"></bean>
	
	<bean id="bean1" class="com.tracker.pojo.User">
		//基本类型、String、Integer等类型注入
		<property name="username" value="zhangsan"></property>
		//外部Bean注入
		<property name="bean1" ref="helloSpring"></property>
		//内部Bean注入
		<property name="helloBean">
				<bean class="com.tracker.pojo.HelloBean">
		</property>
		//List集合使用<list>,Set集合使用<set>,数组使用<array>
		<property name="list">
			<list>
				<value>Java</value>
				<value>Spring</value>
			</list>
		</property>
		//Map类型
		<property name="map">
			<entry>
				<key>
						<value>key</value>
				</key>
				<value>value</value>
				//如果键或值是Bean对象,可以把<value>换成<ref>
			</entry>
		</property>
		//注入null值,如果注入空字符串,直接使用<value></value>
		<property name="nullValue">
				<null/>
		</property>
	</bean>

提示:如果属性值中包含XML中的特殊字符(&,<,>,",'),则注入时需要进行处理。
有两种方式:1.使用<![CDATA[特殊字符]]>  2.使用特殊字符的实体引用,例如“&”可以用“&amp;”表示

(2)基于注解的装配方式
使用注解定义Bean:

注解名称说明
@Component表示一个Bean组件。泛化概念,可以标注在任何层次上
@Repository将Dao层的类标识为一个Spring组件
@Service将Service层的类标识为一个Spring组件
@Controller将Controller层的类标识为一个Spring组件

以上4个注解的作用都相同,被这些注解标注的类会创建一个实例被加入到Spring容器中。开发中常用使用此种方式。

//@Service("userService")  指定Bean的名字
@Service
public class UserServiceImpl{}

使用注解实现依赖注入(基于注解的自动装配):

注解名称说明参数
@Autowired用于对Bean的属性变量,属性的Setter方法和构造方法进行标注,以配合对应的注解处理器完成Bean的自动配置工作,默认按照Bean的类型进行装配required:指定装配的Bean是否必须,默认:true
@Resource作用与@Autowired一样,默认按照Bean的实例名称进行装配(不写参数),再按照类型进行匹配。name:指定Bean的名称 。type:指定Bean的类型
@Qualifier与@Autowired注解配合使用,会按照Bean的实例名称进行装配,名称由@Qualifier的参数指定value:指定Bean的名称,默认:“”
@Controller
public class UserController{
	//@Resource   Java提供的注解,不写参数时先按Bean的名称装配,找不到按类型装配
	//@Qualifier("userService") 与@Autowired 一起使用,按Bean的名称装配
	@Autowired    //Spring提供的注解
	private UserService userService;
	
	@Autowired
	public void setUserService(@Qualifier("userService")UserService userService){}
}

使用注解装配,需要在配置文件中开启Spring的组件扫描功能:

<?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.3.xsd">
  <!--开启组件扫描功能,base-package:指定要扫描的包,有多个包可使用逗号隔开-->
	<context:component-scan base-package="com.tracker"/>
</beans>

首先要在配置文件引入context命名空间的声明,开启注解扫描功能后,Spring会扫描指定包中的所有类,以获取Bean的定义信息。
提示:spring4.0以上版本在使用注解装配时,需要向项目中引入Spring AOP的JAR包

(3)基于XML的自动装配方式
在<bean>元素中包含一个autowired属性,可以通过该属性来实现自动装配。
autowired属性值:

属性值说明
default默认。由标签中的default-autowired属性值确定。
byName根据属性名自动装配。找出Bean的id属性与setter方法匹配的Bean进行自动注入,否则什么也不做
byType根据属性类型自动装配。找出与依赖属性类型相同的Bean进行注入。如果有多个匹配就抛出异常,如果没有就什么都不做
constructor与byType的方式类似,应用于构造器参数
no在默认情况下不使用自动装配,Bean的依赖必须通过ref元素定义
<bean id="userDao" class="com.tracker.pojo.UserDaoImpl"></bean>
<bean id="userService" class="com.tracker.pojo.UserServiceImpl" autowire="byName"></bean>

4、Bean的作用域

作用域名称说明
singleton (单例)默认值,该模式下Bean在Spring容器中只有一个实例,,每次获取都返回同一个实例
prototype(原型)每次获取时,Spring容器都会创建一个新的实例返回
request再一次Http请求中,容器会返回该Bean的同一个实例,对不同的HTTP请求产生一个新的Bean,且该Bean只在当前HTTP request内有效
session与request相同,只是作用域提升到Session
global session在一个全局的HTTP Session中,容器会返回该Bean的同一个实例,仅在使用portlet上下文时有效
application为每一个ServletContext对象创建一个实例,仅在web相关的ApplicationContext中生效
websocket为每个websocket对象创建一个实例,仅在web相关的ApplicationContext中生效

指定Bean的作用域:

<bean id="user" calss="User" scope="prototype"></bean>
@Scope("singleton")
@Service
public class UserServiceImpl{}

5、Bean的生命周期
Spring框架的容器可以管理Singleton作用域的Bean的声明周期,在此作用域下,Spring容器可以精确的知道该Bean何时被创建、何时初始化完成以及何时被销毁、对于prototype作用的Bean,Spring只负责创建,当容器创建了Bean的实例后就交给客户端代码来管理。
Bean的生命周期执行过程:

(1)根据配置情况实例化Bean
(2)利用依赖注入完成Bean中所有的属性值的配置注入
(3)如果Bean实现了BeanNameAware接口,则Spring调用Bean的setBeanName()方法传入当前Bean的id值
(4)如果Bean实现了BeanFactoryAware接口,则Spring调用setBeanFactory()方法传入当前工厂实例的引用
(5)如果Bean实现了ApplicationContextAware接口,则Spring调用setApplicationContext()方法传入当前ApplicationContext实例的引用
(6)如果BeanPostProcesso和Bean关联,则Spring将调用该接口的预初始化方法postProcessBeforeInitialization()对Bean进行加工操作,Spring的AOP就是通过它实现的
(7)如果Bean实现了InitializingBean接口,则Spring将调用afterPropertiesSet()方法。
(8)如果在配置文件中通过init-method属性定义了初始化方法,则调用该初始化方法
(9)如果有BeanPostProcessor和Bean关联,则Spring将调用该接口的初始化方法postProcessAfterInitialization()。此时,Bean已经可以被系统使用了
(10)如果在<bean>中指定了该Bean的作用范围为Singleton,则将该Bean放入SpringIoC缓存池中,将触发Spring对该Bean的生命周期管理。如果指定为prototype,则将该Bean交给调用者。由调用者管理该Bean的生命周期
(11)如果Bean实现了DisposableBean接口,则Spring会调用destory()将Spring中的Bean销毁;可以在配置文件中通过destory-method属性指定Bean的销毁方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值