👉博主介绍: 博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家,WEB架构师,阿里云专家博主,华为云云享专家,51CTO 专家博主
一、什么是 XmlClassPathApplicationContext
XmlClassPathApplicationContext
是一个在 Spring Framework 中使用的特殊类型的应用上下文。它是通过 XML 文件来配置和初始化 Spring 容器的一种方式。
XmlClassPathApplicationContext
类是 Spring Framework 中的一个类,它实现了 ApplicationContext
接口。它从类路径中的 XML 文件加载配置信息,并使用这些配置信息来创建和管理应用程序的对象和依赖关系。
通过 XmlClassPathApplicationContext
,您可以使用 XML 文件来定义和组织应用程序的组件,如 bean 定义、依赖关系、配置属性等。Spring 容器会根据这些配置信息创建和管理这些组件,使您能够以一种声明性的方式构建和配置应用程序。
下面说明 XmlClassPathApplicationContext
加载 XML 配置文件并获取 bean:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.XmlClassPathApplicationContext;
/**
*
* @description: MyApp
* @copyright: @Copyright (c) 2022
* @company: Aiocloud
* @author: pany
* @version: 1.0.0
* @createTime: 2023-08-15 12:48
*/
public class MyApp {
public static void main(String[] args) {
// 创建 XmlClassPathApplicationContext 对象,指定 XML 配置文件的路径
ApplicationContext context = new XmlClassPathApplicationContext("applicationContext.xml");
// 从容器中获取名为 "myBean" 的 bean
MyBean myBean = (MyBean) context.getBean("myBean");
// 使用 myBean 对象进行操作
myBean.doSomething();
}
}
我们创建了一个 XmlClassPathApplicationContext
对象,并指定了 XML 配置文件的路径。然后,我们使用 getBean()
方法从容器中获取名为 "myBean" 的 bean,并进行相关操作。
二、什么是 Bean
Bean 是 Spring Framework 中的一个概念,它代表了应用程序中的一个可重用组件。在 Spring 中,Bean 是由 Spring 容器创建、组装和管理的对象。
Bean 可以是任何 Java 对象,例如普通的 POJO(Plain Old Java Object)类、数据访问对象、服务类、控制器等。Spring 容器负责创建这些 Bean,并在应用程序的不同部分之间进行依赖注入。
使用 Spring 的 IoC(Inversion of Control)功能,您可以通过配置文件(如 XML 文件)或注解来定义和配置 Bean。Spring 容器会根据这些配置信息创建 Bean,并在需要时将它们注入到其他 Bean 中。
以下说明如何在 Spring 中定义和使用一个简单的 Bean:
/**
*
* @description: MyBean
* @copyright: @Copyright (c) 2022
* @company: Aiocloud
* @author: pany
* @version: 1.0.0
* @createTime: 2023-08-15 12:48
*/
public class MyBean {
private String message;
// 构造函数
public MyBean() {
}
// 设置消息
public void setMessage(String message) {
this.message = message;
}
// 执行操作
public void doSomething() {
System.out.println("Message: " + message);
}
}
MyBean
是一个简单的 POJO 类,它有一个成员变量 message
和一个方法 doSomething()
。通过配置文件或注解,您可以告诉 Spring 如何创建和配置这个 Bean,然后在应用程序中使用它。
三、依赖注入
依赖注入(Dependency Injection,简称DI)是软件开发中的一种设计模式,也是Spring框架的核心概念之一。它允许对象通过外部提供依赖项来实现松耦合。
在DI中,对象的依赖关系被“注入”到对象中,而不是对象自己创建或管理依赖关系。这有助于实现更好的关注点分离,提高代码的灵活性和可测试性。
在Spring中,有不同的方式来进行依赖注入: 1. 构造函数注入(Constructor Injection):依赖项通过对象的构造函数来注入。例如:
/**
*
* @description: MyService
* @copyright: @Copyright (c) 2022
* @company: Aiocloud
* @author: pany
* @version: 1.0.0
* @createTime: 2023-08-15 12:48
*/
public class MyService {
private MyRepository repository;
public MyService(MyRepository repository) {
this.repository = repository;
}
// 使用repository进行操作
}
在上面的例子中, MyService
类通过构造函数接收一个 MyRepository
对象,并将其赋值给成员变量 repository
。这样, MyService
就可以使用 repository
进行操作。
2. Setter方法注入(Setter Injection):依赖项通过对象的setter方法来注入。例如:
/**
*
* @description: MyService
* @copyright: @Copyright (c) 2022
* @company: Aiocloud
* @author: pany
* @version: 1.0.0
* @createTime: 2023-08-15 12:48
*/
public class MyService {
private MyRepository repository;
public void setRepository(MyRepository repository) {
this.repository = repository;
}
// 使用repository进行操作
}
在上面的例子中, MyService
类提供了一个 setRepository
方法,通过该方法将 MyRepository
对象注入到成员变量 repository
中。
3. 接口注入(Interface Injection):依赖项通过接口方法来注入。这种方式相对较少使用,一般使用构造函数或setter方法注入就足够了。
通过依赖注入,我们可以将对象的依赖关系外部化,使得对象之间的关系更加灵活和可配置。这样,我们可以更方便地替换、扩展或重用依赖项,同时也更容易进行单元测试和模块化开发。
四、使用 depends-on属性
depends-on
属性用于在 Spring 中指定 Bean 之间的依赖关系。通过设置 depends-on
属性,您可以确保某个 Bean 在另一个 Bean 之前被初始化和创建。
以下说明如何使用 depends-on
属性:
<bean id="beanA" class="com.example.BeanA" />
<bean id="beanB" class="com.example.BeanB" depends-on="beanA" />
我们有两个 Bean: beanA
和 beanB
。 beanB
依赖于 beanA
,因此我们在 beanB
的定义中使用 depends-on
属性来指定它所依赖的 Bean。
这样,当 Spring 容器初始化时,它会先创建和初始化 beanA
,然后再创建和初始化 beanB
。确保 beanA
在 beanB
之前被创建,以满足依赖关系。
需要注意的是, depends-on
属性接受一个逗号分隔的 Bean ID 列表,以指定多个依赖项。例如:
<bean id="beanC" class="com.example.BeanC" depends-on="beanA,beanB" />
beanC
依赖于 beanA
和 beanB
,因此它会在这两个 Bean 之后被创建和初始化。
使用 depends-on
属性可以确保 Bean 之间的正确初始化顺序,以满足依赖关系。这在某些情况下非常有用,特别是当某个 Bean 需要依赖其他 Bean 的状态或属性时。
五、懒加载 Bean
在Spring中,可以使用 lazy-init
属性来实现Bean的懒加载。懒加载是指在需要使用Bean时才进行初始化和创建,而不是在容器启动时就立即创建。
要使用懒加载,可以在Bean的定义中设置 lazy-init
属性为 true
。如下:
<bean id="myBean" class="com.example.MyBean" lazy-init="true" />
myBean
Bean被设置为懒加载。当Spring容器启动时,不会立即创建和初始化 myBean
,而是在第一次访问 myBean
时才进行创建和初始化。
懒加载对于那些在应用启动时可能不会被立即使用的大型或资源密集型Bean特别有用。通过懒加载,可以减少应用启动时间和内存占用。
需要注意的是,懒加载只适用于单例作用域的Bean。原型作用域的Bean无法进行懒加载,因为每次请求都会创建一个新的实例。
另外,可以通过在 @Component
注解或 @Bean
方法上使用 @Lazy
注解来实现懒加载。例如:
/**
*
* @description: MyComponent
* @copyright: @Copyright (c) 2022
* @company: Aiocloud
* @author: pany
* @version: 1.0.0
* @createTime: 2023-08-15 12:48
*/
@Component
@Lazy
public class MyComponent {
// ...
}
或者:
/**
*
* @description: MyComponent
* @copyright: @Copyright (c) 2022
* @company: Aiocloud
* @author: pany
* @version: 1.0.0
* @createTime: 2023-08-15 12:48
*/
@Configuration
public class MyConfig {
@Bean
@Lazy
public MyBean myBean() {
return new MyBean();
}
}
通过以上方式,可以将对应的组件或Bean设置为懒加载。
六、自动注入
在Spring中,可以使用自动注入(Autowiring)来自动解析和注入Bean之间的依赖关系,而无需显式地进行配置。自动注入可以减少手动配置的工作量,提高开发效率。
要使用自动注入,可以在需要注入依赖的字段、构造函数或setter方法上使用 @Autowired
注解。Spring容器会自动查找匹配的Bean并将其注入。
以下是不同的自动注入方式: 1. 字段注入:
/**
*
* @description: MyComponent
* @copyright: @Copyright (c) 2022
* @company: Aiocloud
* @author: pany
* @version: 1.0.0
* @createTime: 2023-08-15 12:48
*/
@Component
public class MyComponent {
@Autowired
private MyDependency dependency;
// ...
}
在上面的例子中, MyDependency
会被自动注入到 MyComponent
中的 dependency
字段中。
2. 构造函数注入:
/**
*
* @description: MyComponent
* @copyright: @Copyright (c) 2022
* @company: Aiocloud
* @author: pany
* @version: 1.0.0
* @createTime: 2023-08-15 12:48
*/
@Component
public class MyComponent {
private MyDependency dependency;
@Autowired
public MyComponent(MyDependency dependency) {
this.dependency = dependency;
}
// ...
}
在上面的例子中, MyDependency
会通过构造函数注入到 MyComponent
中。
3. Setter方法注入:
/**
*
* @description: MyComponent
* @copyright: @Copyright (c) 2022
* @company: Aiocloud
* @author: pany
* @version: 1.0.0
* @createTime: 2023-08-15 12:48
*/
@Component
public class MyComponent {
private MyDependency dependency;
@Autowired
public void setDependency(MyDependency dependency) {
this.dependency = dependency;
}
// ...
}
在上面的例子中, MyDependency
会通过setter方法注入到 MyComponent
中。
自动注入还支持 @Qualifier
注解用于解决多个匹配的Bean的歧义性,以及 @Primary
注解用于指定首选的Bean。
需要注意的是,为了使用自动注入,需要确保已经在Spring配置中启用了自动注入的功能,例如通过在配置类上添加 @EnableAutoConfiguration
或在XML配置文件中进行相应的配置。
自动注入使得依赖管理更加方便,减少了手动配置的繁琐过程,提高了代码的可读性和可维护性。
七、Bean 的作用域
Bean的作用域定义了在Spring容器中创建和管理Bean实例的生命周期和可见范围。Spring框架提供了多种作用域选项,可以根据应用程序的需求来选择适合的作用域。
以下是Spring框架中常用的Bean作用域:
- Singleton(默认):在整个应用程序中只创建一个Bean实例。无论何时请求该Bean,都会返回同一个实例。
- Prototype:每次请求时都会创建一个新的Bean实例。每个实例都是独立的,拥有自己的状态和属性。
- Request:在每个HTTP请求中创建一个新的Bean实例。对于Web应用程序,每个请求都会有自己的实例。
- Session:在每个用户会话中创建一个新的Bean实例。对于Web应用程序,每个用户会话都会有自己的实例。
- Global Session:在全局HTTP会话中创建一个新的Bean实例。仅适用于基于Portlet的Web应用程序。
除了以上常用的作用域,Spring还提供了其他一些作用域选项,如WebSocket、Application等,可以根据特定的应用场景选择合适的作用域。
通过合理选择Bean的作用域,可以控制Bean的生命周期和共享性。例如,Singleton适用于那些只需要一个实例的情况,而Prototype适用于需要频繁创建新实例的情况。
可以通过在Bean定义中使用 @Scope
注解或在XML配置文件中设置 scope
属性来指定Bean的作用域。例如:
@Component
@Scope("prototype")
public class MyBean {
// ...
}
或
<bean id="myBean" class="com.example.MyBean" scope="prototype" />
选择适当的Bean作用域对于确保应用程序的正确性和性能是非常重要的。
相关文章: 【手撕 Spring】bean的作用域 https://jiliu.blog.csdn.net/article/details/131993122
八、生命周期的回调
在Spring框架中,Bean的生命周期可以通过使用特定的回调方法来管理。这些回调方法允许您在Bean的不同生命周期阶段执行自定义的逻辑。
以下是常用的Bean生命周期回调方法:
- 初始化回调:
@PostConstruct
:使用此注解标记的方法将在Bean的依赖注入完成后立即调用,用于执行初始化逻辑。InitializingBean
接口:实现该接口并实现其中的afterPropertiesSet()
方法,该方法将在依赖注入完成后立即调用。
- 销毁回调:
@PreDestroy
:使用此注解标记的方法将在Bean销毁之前调用,用于执行清理和资源释放逻辑。DisposableBean
接口:实现该接口并实现其中的destroy()
方法,该方法将在Bean销毁之前调用。
除了上述方法,您还可以使用 init-method
和 destroy-method
属性来指定自定义的初始化和销毁回调方法。例如,在XML配置文件中:
<bean id="myBean" class="com.example.MyBean" init-method="init" destroy-method="cleanup" />
在上述示例中,当Bean被创建时会调用 init
方法,而在Bean销毁之前会调用 cleanup
方法。
这些生命周期回调方法使您能够在Bean的创建和销毁过程中执行特定的逻辑,例如初始化配置、资源分配和释放等。通过合理使用这些回调方法,可以确保Bean的正确初始化和销毁,以及管理与Bean相关的资源。
九、Bean 定义的继承
Bean定义的继承是指在Spring中可以通过一个Bean定义派生出另一个Bean定义,从而实现Bean定义的重用和扩展。通过继承,可以减少重复的配置,提高代码的可维护性和可读性。
在Bean定义中,可以使用 parent
属性指定父Bean的名称或ID,从而实现继承。子Bean将继承父Bean的配置和属性,并可以对其进行扩展或覆盖。
以下是一个示例,展示了如何在Spring中使用Bean定义的继承:
<bean id="parentBean" class="com.example.ParentBean">
<property name="property1" value="value1" />
<property name="property2" value="value2" />
</bean>
<bean id="childBean" class="com.example.ChildBean" parent="parentBean">
<property name="property2" value="new value2" />
<property name="property3" value="value3" />
</bean>
我们定义了一个名为 parentBean
的父Bean和一个名为 childBean
的子Bean。 childBean
通过 parent
属性指定了 parentBean
作为其父Bean。
子Bean childBean
继承了父Bean parentBean
的配置和属性,同时可以对其进行扩展或覆盖。在这个例子中,子Bean覆盖了父Bean的 property2
属性,并添加了一个新的 property3
属性。
通过Bean定义的继承,可以实现Bean配置的重用和扩展,避免了重复的配置。这对于具有类似配置的多个Bean非常有用,可以提高代码的可维护性和可读性。