前言

以前学习Spring框架的时候,总结了几种Bean的加载方式,不过老师说还有其它的加载方式,以下八种并不是全部,但也足以用来做很多事情了。

注意以下是Spring中Bean的加载方式,不是SpringBoot,但其中的很多东西是相通的,尤其是Bean的注入方式、适用场景等,在本文中也有介绍的。

分享给大家一起学习,如有错误的地方,麻烦各位在评论区帮我指出。

1.xml <bean>

被配置的bean需要有无参数的构造函数

<?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">
	<!-- xml方式声明自己开发的bean -->
	<bean id="user" class="cn.sticki.blog.pojo.domain.User" />
	<!-- xml方式声明第三方bean -->
	<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"/>
</beans>

2.xml:context 注解(@Component 4个@Bean)

使用组件扫描,指定加载bean的位置,spring会自动扫描这个包下的文件。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       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
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
    ">

    <!-- 组件扫描,指定加载bean的位置 -->
    <context:component-scan base-package="cn.sticki.bean,cn.sticki.config"/>
</beans>

然后在需要被加载的类名上添加@Component注解。也可以使用@Controller、@Service、@Repository定义bean。

@Service
publice class UserServiceImpl implements UserService {
}

使用@Bean定义第三方bean,并将所在类定位为配置类或Bean

@Configuration  // 或使用@Component
public class DBConfig {
    @Bean
    public DruidDataSource dataSource(){
        DruidDataSource ds = new DruidDataSource();
        return ds;
    } 
}

3.配置类 扫描 注解(@Component 4个@Bean)

使用 AnnotationConfigApplicationContext(SpringConfig.class); 来获取 ApplicationContext

public class AppObject {
    public static void main() {
        ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        SpringConfig config = ctx.getBean("Config", SpringConfig.class);
        // 两次获取的是同一个对象
        config.user();
        config.user();
    }
}

和上面的第二种有点类似,就是包的扫描方式有所改变。

@ComponentScan({"cn.sticki.bean","cn.sticki.config"})
public class SpringConfig {
    @Bean
    public DogFactoryBean dog(){
        return new DogFactoryBean();
    }
}

3.1FactoryBean接口

初始化实现FactoryBean接口的类,实现对bean加载到容器之前的批处理操作。

public class DogFactoryBean implements FactoryBean<Dog> {
    @Override
    public Dog getObject() throws Exception {
        return new Dog();
    }
    @Override
    public Class<?> getObjectType() {
        return Dog.class;
    }
}

在下面的bean中,显示的表示为配置DogFactoryBean ,但实际上配置的是 Dog

@Component
public class SpringConfig {
    @Bean
    public DogFactoryBean dog(){
        return new DogFactoryBean();
    }
}

3.2@ImportResource注解

用于加载配置类并加载配置文件(系统迁移)

@Configuration
@ComponentScan("cn.sticki.bean")
@ImportResource("applicationContext.xml")
public class SpringConfig {
}

3.3proxyBeanMethods属性

使用 proxyBeanMethods = true 可以保障调用此类中的方法得到的对象是从容器中获取的,而不是重新创建的,但要求必须是通过此类调用方法获得的bean。

@Configuration(proxyBeanMethods = true)
public class SpringConfig {
    @Bean
    public User user() {
        System.out.println("user init...");
        return new User();
    }
}

4.@Import导入bean的类

使用@Import注解导入要注入的bean对应的字节码

@Import(User.class)
public class SpringConfig {
}

而被导入的bean无需使用注解声明为bean

public class User{
}

这种形式可以有效的降低源代码与spring技术的耦合度(无侵入),在spring技术底层及诸多框架的整合中大量使用。

使用这种方法可以加在配置类,且也可以加在配置类当中的bean。

5.AnnotationConfigApplicationContext调用register方法

在容器初始化完毕后使用容器对象手动注入bean

public class App {
    public static void main() {
        ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        ctx.register(User.class);
        // 打印容器中当前的所有bean
        String[] names = ctx.getBeanDefinitionNames();
        for (String name: names) {
            System.out.println(name);
        }
    }
}

必须在容器初始化之后才能使用这种方法。如果重复加载同一个bean,后面加载的会覆盖前面加载的。

6.@Import导入ImportSelector接口

导入实现了ImportSelector接口的类,实现对导入源的编程式处理

public class MyImportSelector implements ImportSelector {
    public String selectImports(AnnotationMetadata metadata) {
        // 使用metadata可以获取到导入该类的元类的大量属性,通过对这些属性进行判断,可以达到动态注入bean的效果
        boolean flag = metadata.hasAnnotation("org.springframework.context.annotation.Import");
        if(flag) {
            return new String[]{"cn.sticki.pojo.User"};
        }
        return new String[]{"cn.sticki.pojo.Dog"};
    }
}

调用处:

@Import(MyImportSelector.class)
public class SpringConfig {
}

7.@Import导入ImportBeanDefinitionRegistrar接口

导入实现了ImportBeanDefinitionRegistrar接口的类,通过BeanDefinition的注册器注册实名bean,实现对容器中bean的绑定,例如对现有bean的覆盖,进而达成不修改源代码的情况下更换实现的效果。

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    public String registrarBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
        // 使用元数据去做判定,然后再决定要注入哪些bean
        BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(User.class).getBeanDefinition();
        registry.registerBeanDefinition("user",beanDefinition);
    }
}

调用处和上面第六种方式差不多。

8.@Import导入BeanDefinitionRegistryPostProcessor接口

导入实现了BeanDefinitionRegistryPostProcessor接口的类,通过BeanDefinition的注册器注册实名bean,实现对容器中bean的最终裁定。其在@Import中的加载顺序为最后一个加载,可以用来做bean覆盖的最终裁定。

public class MyPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        // 注意这里注册的是BookServiceImpl4
        BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(BookServiceImpl4.class).getBeanDefinition();
        registry.registerBeanDefinition("bookService",beanDefinition);
    }
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    }
}

调用处:

// 按照先后顺序加载,但 MyPostProcessor.class 最后才加载
@Import(BookServiceImpl1.class,MyPostProcessor.class, BookServiceImpl.class, MyImportSelector.class)
public class SpringConfig {
}

后记

这八种加载方式几乎可以满足我们所需要的全部场景了,但一般场景下,我们用的其实也就只有那两三种,真正掌握这八种加载方式的朋友,肯定是大佬了。

到此这篇关于Spring Bean的8种加载方式总结的文章就介绍到这了,更多相关Spring Bean加载方式内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

Spring Bean的8种加载方式总结的更多相关文章

  1. android – 在Jelly Bean平板电脑中隐藏系统栏(生根)

    我有一个AndroidJellyBean平板电脑已经扎根并且试图运行一个应用程序,其中包含隐藏系统栏的代码,但它没有被隐藏,任何人都可以帮助我解决这个问题.获取终端输出:结果包(00000000’….’)虽然我正在获得许可的祝酒:超级用户日志屏幕截图:解决方法当引入ICS时,systemUI类的进程ID从79更改为42.下面的代码适用于您的应用可能正在运行的任何Android版本.

  2. vue自定义加载指令v-loading占位图指令v-showimg

    这篇文章主要为大家介绍了vue自定义加载指令和v-loading占位图指令v-showimg的示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  3. Java Bean 作用域及它的几种类型介绍

    这篇文章主要介绍了Java Bean作用域及它的几种类型介绍,Spring框架作为一个管理Bean的IoC容器,那么Bean自然是Spring中的重要资源了,那Bean的作用域又是什么,接下来我们一起进入文章详细学习吧

  4. Spring JdbcTemplate执行数据库操作详解

    JdbcTemplate是Spring框架自带的对JDBC操作的封装,目的是提供统一的模板方法使对数据库的操作更加方便、友好,效率也不错,这篇文章主要介绍了Spring JdbcTemplate执行数据库操作,需要的朋友可以参考下

  5. Spring Batch批处理框架操作指南

    Spring Batch 是 Spring 提供的一个数据处理框架。企业域中的许多应用程序需要批量处理才能在关键任务环境中执行业务操作,这篇文章主要介绍了Spring Batch批处理框架操作指南,需要的朋友可以参考下

  6. Spring详细讲解@Autowired注解

    @Autowired注解可以用在类属性,构造函数,setter方法和函数参数上,该注解可以准确地控制bean在何处如何自动装配的过程。在默认情况下,该注解是类型驱动的注入

  7. 使用Spring AOP实现用户操作日志功能

    这篇文章主要介绍了使用Spring AOP实现了用户操作日志功能,功能实现需要一张记录日志的log表,结合示例代码给大家讲解的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  8. JavaScript实现动态加载删除表格

    这篇文章主要为大家详细介绍了JavaScript实现动态加载删除表格,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  9. Spring Security认证器实现过程详解

    一些权限框架一般都包含认证器和决策器,前者处理登陆验证,后者处理访问资源的控制,这篇文章主要介绍了Spring Security认证器实现过程,需要的朋友可以参考下

  10. spring学习JdbcTemplate数据库事务管理

    这篇文章主要为大家介绍了spring学习JdbcTemplate数据库事务管理,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

随机推荐

  1. 基于EJB技术的商务预订系统的开发

    用EJB结构开发的应用程序是可伸缩的、事务型的、多用户安全的。总的来说,EJB是一个组件事务监控的标准服务器端的组件模型。基于EJB技术的系统结构模型EJB结构是一个服务端组件结构,是一个层次性结构,其结构模型如图1所示。图2:商务预订系统的构架EntityBean是为了现实世界的对象建造的模型,这些对象通常是数据库的一些持久记录。

  2. Java利用POI实现导入导出Excel表格

    这篇文章主要为大家详细介绍了Java利用POI实现导入导出Excel表格,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  3. Mybatis分页插件PageHelper手写实现示例

    这篇文章主要为大家介绍了Mybatis分页插件PageHelper手写实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  4. (jsp/html)网页上嵌入播放器(常用播放器代码整理)

    网页上嵌入播放器,只要在HTML上添加以上代码就OK了,下面整理了一些常用的播放器代码,总有一款适合你,感兴趣的朋友可以参考下哈,希望对你有所帮助

  5. Java 阻塞队列BlockingQueue详解

    本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景,通过实例代码介绍了Java 阻塞队列BlockingQueue的相关知识,需要的朋友可以参考下

  6. Java异常Exception详细讲解

    异常就是不正常,比如当我们身体出现了异常我们会根据身体情况选择喝开水、吃药、看病、等 异常处理方法。 java异常处理机制是我们java语言使用异常处理机制为程序提供了错误处理的能力,程序出现的错误,程序可以安全的退出,以保证程序正常的运行等

  7. Java Bean 作用域及它的几种类型介绍

    这篇文章主要介绍了Java Bean作用域及它的几种类型介绍,Spring框架作为一个管理Bean的IoC容器,那么Bean自然是Spring中的重要资源了,那Bean的作用域又是什么,接下来我们一起进入文章详细学习吧

  8. 面试突击之跨域问题的解决方案详解

    跨域问题本质是浏览器的一种保护机制,它的初衷是为了保证用户的安全,防止恶意网站窃取数据。那怎么解决这个问题呢?接下来我们一起来看

  9. Mybatis-Plus接口BaseMapper与Services使用详解

    这篇文章主要为大家介绍了Mybatis-Plus接口BaseMapper与Services使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  10. mybatis-plus雪花算法增强idworker的实现

    今天聊聊在mybatis-plus中引入分布式ID生成框架idworker,进一步增强实现生成分布式唯一ID,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部