【Spring.Framework】【IoC】Spring容器,Bean及Bean的实例化

本文详细介绍了Spring框架中的IoC容器概念及其核心组件BeanFactory和ApplicationContext的作用。阐述了如何通过XML配置文件、注解及Java配置等方式来定义Bean,并展示了如何利用Spring容器实例化和管理Bean。

Spring IoC 容器 和 Beans

IoC也称作dependency injection(DI).

org.springframework.beansorg.springframework.context库时IoC容器的基础。

BeanFactory接口提供了管理任意类型对象的机制。ApplicationContext是BeanFactory的子接口,它添加了AOP,message resource handling,event publication等特征。

BeanFactor提供了基本的功能和配置框架,而ApplicationContext添加了更多的企业化的功能。ApplicationContext时BeanFactory的超集。


Spring中,IoC容器管理的对象称为benas;


Spring容器

接口org.springframework.context.ApplicationContext代表Spring IoC容器,负责实例化,配置,装配beans。Spring容器通过读取配置元数据来获得实例化,配置,装配的对象的说明。配置元数据(Configuration Metadata)可以时XML文件,Java注解Annotation,或者Java Doc。

Spring提供了一些ApplicationContext接口的直接实现;例如在一个standalone应用中,通常创建一个ClassPathXmlApplicationContext或FileSystemXmlApplicationContext实例。XML是定义配置元数据的传统形式,在其中可以指定容器使用java 注解或 java code作为实际的元数据配置的形式。

在大部分的应用中,并不需要显式的实例化Spring IoC容器的实例(ApplicationContext),例如在web应用中,通过在web.xml中进行配置。


Configuration Metadata

传统上,使用基于XML格式的文件作为配置文件。

也可以使用基于注解的配置和基于java的配置。


基于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.xsd">
	
	<!-- Root Context: defines shared resources visible to all other web components -->
		
</beans>

实例化容器

示例:

ApplicationContext context =
    new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});

bean的定义可以放在多个XML文件中。

可以使用上面的构造函数将这些文件传入;或者,使用<import>元素从其他文件加载bena定义,例如:

<beans>
    <import resource="services.xml"/>
    <import resource="resources/messageSource.xml"/>
    <import resource="/resources/themeSource.xml"/>

    <bean id="bean1" class="..."/>
    <bean id="bean2" class="..."/>
</beans>

不推荐使用父路径,即在路径最前面使用“/”)。


使用容器

使用ApplicationContext对象的方法 :

T getBean(String name, Class<T> requriedType);

获得bean的实例。

例如:

// create and configure beans
ApplicationContext context =
    new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});

// retrieve configured instance
PetStoreService service = context.getBean("petStore", PetStoreService.class);

// use configured instance
List<String> userList = service.getUsernameList();


Spring Bean

在Spring容器中,使用BeanDefinition对象来表示bean定义,BeanDefiniton对象包含下列信息:

  • a package-qualified class name —— 该bean所定义的实际的类名
  • bean behavior configuration elements —— 例如scope, lifecycle, callback等
  • collaborator dependencies —— 该bean中所引用的其他的bean
  • 其他配置 —— 如连接池的大小等

Bean definition的属性

  • class
  • name
  • scope
  • constructor arguments
  • properties
  • autowiring mode
  • lazy-initialization mode
  • initialization method
  • destruction method

Bean的命名

一个Bean通常只有一个标识符;如果需要多个的话,可以将其他的标识符看作是别名(aliases).

在基于XML格式的配置中,使用 id 或 name 属性指定bean的标识。

在bean定义的外部,可以指定bean的别名;例如,在基于XML的配置中:

<alias name="fromName" alias="toName" />

他们实际都指向同一个bena对象。


实例化Bean

如果使用基于XML的配置,需要在<bean>元素的 class 属性中指定需要实例化对象的类型。class 属性映射到 BeanDefiniton对象的Class属性。


使用构造函数实例化

大部分的spring用户倾向于使用仅有默认构造函数的JavaBean,并提供setter和getter方法。


使用静态厂方法实例化

例如:

<bean id="clientService"
    class="examples.ClientService"
    factory-method="createInstance"/>

public class ClientService {
    private static ClientService clientService = new ClientService();
    private ClientService() {}

    public static ClientService createInstance() {
        return clientService;
    }
}


使用实例厂对象的方法实例化

例如:

<bean id="serviceLocator" class="examples.DefaultServiceLocator">
    <!-- inject any dependencies required by this locator bean -->
</bean>

<bean id="clientService"
    factory-bean="serviceLocator"
    factory-method="createClientServiceInstance"/>

<bean id="accountService"
    factory-bean="serviceLocator"
    factory-method="createAccountServiceInstance"/>

public class DefaultServiceLocator {

    private static ClientService clientService = new ClientServiceImpl();
    private static AccountService accountService = new AccountServiceImpl();

    private DefaultServiceLocator() {}

    public ClientService createClientServiceInstance() {
        return clientService;
    }

    public AccountService createAccountServiceInstance() {
        return accountService;
    }

}





 






这段错误信息表明,在程序运行期间发生了一个 `ClassCastException` (类型转换异常),具体是在尝试将一个 `ReferencePipeline$2` 类型的对象强制转换成 `User` 类型时出错了。这通常是由于使用 Java Stream API 进行操作后的结果未能正确收集为期望类型的对象所引起的。 ### 错误原因分析 1. **Stream 终端操作的结果类型不匹配** 当我们使用流式处理数据(如过滤、映射等中间操作)之后,如果没有指定正确的终端操作来返回预期的数据结构或元素类型,就可能导致最终生成的是某个内部管道类(例如这里的 `ReferencePipeline$2`),而不是我们需要的具体业务对象实例(这里应该是 `User`)。 2. **常见的 Stream 收集方式问题** 在使用流的操作链路结束时,应该选择合适的终结方法确保输出符合预期: - 如果希望获取单个元素,应该使用 `.findFirst()` 或者其他能够保证只返回单一值的方法; - 若想获得集合形式的结果,则需调用类似于 `.collect(Collectors.toList())` 的收集器。 3. **可能的代码缺陷位置** 报错发生在 `getUserById` 方法内的第 36 行,结合提供的堆栈跟踪信息推测可能是由于在此处进行了不当的类型断言或者是 stream 链未正确终止所致。 ### 解决方案建议 为了修复这个问题,请检查并调整涉及 Streams 和类型转换的相关部分代码如下所示: #### 建议修改后的代码片段 ```java // Assuming you have a collection or repository that contains users. public Optional<User> getUserById(Long id) { return userRepository.findAll().stream() .filter(user -> user.getId().equals(id)) .findFirst(); // Use findFirst() instead of direct casting } // When using the service layer to call this method, Optional<User> optionalUser = userService.getUserById(userId); if (optionalUser.isPresent()){ User foundUser = optionalUser.get(); // Process with 'foundUser' } else { // Handle not found scenario properly } ``` 此外还需要确认以下几点: - 尽量避免直接对 Stream 结果进行强转,改用适当的终端操作代替; - 确保所有涉及到泛型的地方都已正确定义好参数化类型; - 考虑是否可以在某些地方利用 Optional 来优雅地处理空缺值的情况,进而提升代码健壮性和清晰度。 通过以上改动可以使您的应用程序更好地应对这种特殊情况,并且提高了代码的安全性和可读性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值