Spring注解开发之组件注册(二)
创始人
2024-05-31 04:06:54
0

Spring注解开发之组件注册(一)

5.@Import 给容器导入一个组件

给容器中注册组件

一、包扫描 + 组件标注注解(@Controller/@Service/@Repository/@Component) [自己写的类]

二、@Bean [导入的第三包里面的组件]

三、@Import [快速给容器中导入组件] (@Import{Color.class,Red.class})

    1.@Import(要导入到容器中的组件),容器中就会自动注册这个组件,id默认是组件全名

在这里插入图片描述

​ 2. @ImportSelector: 返回需要导入组建的全类名数组

// 自定义逻辑,返回需要导入的组件
public class MyImportSelector implements ImportSelector {// 返回值就是要导入到容器中的组件的全类名// AnnotationMetadata:当前标注@Import注解类的所有信息@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {return new String[]{"com.lv.pojo.Blue", "com.lv.pojo.Yellow"};// 返回的类注入容器}
}

​ 3.使用ImportBeanDefinitionRegister 手动注册bean到容器中

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {/*** AnnotationMetadata:当前类的注解信息* BeanDefinitionRegistry:注册类* 把所有需要添加到容器中的bean,调用BeanDefinitionRegistry.registerBeanDefinition手动注册*/@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {// 查询容器中是否存在red组件boolean red = registry.containsBeanDefinition("com.xjhqre.pojo.Red");if (red) {// 指定bean的定义信息(bean的类型,bean的scope)BeanDefinition beanDefinition = new RootBeanDefinition(Purple.class);// 第一个参数指定bean的idregistry.registerBeanDefinition("purple", beanDefinition);}}
}

四、使用Spring提供的FactoryBean (工厂Bean)

​ 1.默认获取到的是工厂bean调用getObject创建的对象

​ 2.要获取工厂Bean本身,我们需要给id前面加一个& 即 &colorFactoryBean

// 创建一个Spring定义的FactoryBean
public class ColorFactoryBean implements FactoryBean {// 返回一个Color对象,这个对象会添加到容器中@Overridepublic Color getObject() throws Exception {return new Color();}@Overridepublic Class getObjectType() {return Color.class;}// 返回是否为单例,// true 单实例  在容器中保存一份// false,则每次创建时调用getObject()方法@Overridepublic boolean isSingleton() {return true;}
}

在配置类中导入这个组件!!!

@Test
public void test5() {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig4.class);String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();// 工厂bean获取的是调用getObject创建的对象Object colorFactoryBean = applicationContext.getBean("colorFactoryBean");System.out.println(colorFactoryBean.getClass());// 如果想要拿到colorFactoryBean对象,则需要在传入的id前加一个&标识Object colorFactoryBean2 = applicationContext.getBean("&colorFactoryBean");System.out.println(colorFactoryBean2.getClass());
}

6.Bean生命周期

即bean从创建 ----> 初始化 -----> 销毁的过程

容器管理bean的生命周期;

我们可以自定义初始化和销毁方法,容器在bean进行进行到当前生命周期可以自定义初始化和销毁方法

构造(对象创建)

  • 单实例:在容器启动的时候创建对象
  • 多实例:在每次获取的时候创建对象

初始化

  • 对象完成创建,并赋值好后,调用初始化方法

销毁

  • 单实例:在容器关闭的时候销毁

  • 多实例:容器不会管理这个bean,所以不会调用销毁方法(初始化会在第一次使用这个对象时才会创建)

在这里插入图片描述

初始化和销毁方法:

  1. 通过@Bean注解指定init-method和destroy-method

在这里插入图片描述
在这里插入图片描述

  1. 实现InitializingBean和DisposableBean接口,重写里面的destroy和afterPropertiesSet方法

    1. 通过让bean实现InitializingBean接口来定义初始化逻辑
    2. 通过让bean实现DisposableBean接口来定义销毁逻辑
    3. InitializingBean中有一个方法afterPropertiesSet,该方法在bean创建并赋值后调用
  2. 使用@PostConstruct和@PreDestroy注解

    1. @PostConstruct:在bean创建完成并且属性赋值完成后进行初始化
    2. @PreDestroy:在容器销毁bean之前执行
  3. BeanPostProcessor:接口,bean后置处理器,在bean初始化前后进行一些处理

    1. postProcessBeforeInitialization:在初始化之前执行
    2. postProcessAfterInitialization:在初始化之后执行

BeanPostProcessor执行原理

1.执行populateBean(beanName, mbd, instanceWrapper);给bean进行属性赋值

2.开始initializeBean初始化bean

​ 1.先执行applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);,遍历得到容器中所有的BeanPostProcessor;挨个执行beforeInitialization,一但返回null,跳出for循环,不会执行后面的BeanPostProcessor.postProcessorsBeforeInitialization
​ 2.然后执行invokeInitMethods(beanName, wrappedBean, mbd);执行自定义初始化
​ 3.最后执行applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

7.@Value 属性赋值

在这里插入图片描述

在这里插入图片描述

8.自动装配

Spring利用依赖注入(DI)完成对IOC容器中各个组件的依赖关系赋值

  1. @Autowired:自动注入
    (1)默认优先按照类型去容器中去找对应的组件: applicationContext.getBean(BookDao.class);如果找到了则进行赋值;
    (2)如果找到了多个相同类型的组件,再将属性的名称作为组件的id去容器中查找applicationContext.getBean(“bookDao”)
    (3)@Qualifier(“bookDao”):使用 @Qualifier 指定需要装配的组件的id,而不是使用属性名
    (4)自动装配默认一定要将属性赋值好,没有就会报错,可以使用@Autowired(required = false);来设置为非必须的
    (5)可以利用@Primary:让Spring在进行自动装配的时候,默认使用首选的bean,也可以继续使用@Qualifier(“bookDao”)来明确指定需要装配的bean的名字

  2. Spring还支持使用**@Resource(JSR250)**和@Inject(JSR330) [Java规范注解]

    1. @Resource 可以和@Autowired一样自动装配功能,默认是按照组件名称进行装配的;没有能支持@primary功能没有支持@Autowired(required = false)

    2. @Inject:需要导入java.inject的包,和@Autowired的功能一样

在这里插入图片描述

  1. @Autowired:Spring定义的 @Resource和@Inject都是java规范的AutowiredAnnotationBeanPostProcessor:解析完成自动装配 以上注解都装配进去了

  2. 方法、构造器位置的自动装配

    1. 放在方法上,@Bean+方法参数:参数从容器中获取 ,默认不写@Autowired在这里插入图片描述

    2. 标在构造器上只有一个有参构造器,这个有参构造器的@Autowired可以省略,其参数位置的组件还是可以自动从容器中获取 默认加在ioc容器中的组件,容器会调用无参构造器创建对象,再进行初始化赋值等操作 在这里插入图片描述

  3. Aware注入Spring底层组件 原理

    1. Aware 接口,提供了类似回调函数的功能
    2. 自定义组件想要使用Spring 容器底层的一些组件(ApplicationContext,BeanFactory);自定义组件需要实现xxxAware接口;在创建对象的时候,会调用接口规定的方法注入相关组件
    3. 原理:通过对应的Processor进行处理的 ApplicationContextAware => ApplicationContextAwareProcessor 后置处理器,在创建完bean后,看见bean实现了相关Aware接口,将组件传进来

9.@Profile环境搭建

Spring我们提供的可以根据当前环境,动态的激活和切换一系列组建的功能

​ 开发、生产、测试环境 数据源的不同

@Profile 指定组件在那个环境的情况下才能被注册到容器中,不指定,任何环境下都能注册这组件
在这里插入图片描述

我们需要在项目的src/main/resources目录下新建一个配置文件,例如dbconfig.properties,在其中写上数据库连接的相关信息,如下所示。

db.user=root
db.password=123456
db.driverClass=com.mysql.jdbc.Driver
import javax.sql.DataSource;import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.util.StringValueResolver;import com.mchange.v2.c3p0.ComboPooledDataSource;/**** @author liayun**/
@PropertySource("classpath:/dbconfig.properties") // 加载外部的配置文件
@Configuration
public class MainConfigOfProfile implements EmbeddedValueResolverAware {@Value("${db.user}")private String user;private StringValueResolver valueResolver;private String dirverClass;@Bean("testDataSource")public DataSource dataSourceTest(@Value("${db.password}") String pwd) throws Exception {ComboPooledDataSource dataSource = new ComboPooledDataSource();dataSource.setUser(user);dataSource.setPassword(pwd);dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");dataSource.setDriverClass(dirverClass);return dataSource;}@Bean("devDataSource")public DataSource dataSourceDev(@Value("${db.password}") String pwd) throws Exception {ComboPooledDataSource dataSource = new ComboPooledDataSource();dataSource.setUser(user);dataSource.setPassword(pwd);dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/ssm_crud");dataSource.setDriverClass(dirverClass);return dataSource;}@Bean("prodDataSource")public DataSource dataSourceProd(@Value("${db.password}") String pwd) throws Exception {ComboPooledDataSource dataSource = new ComboPooledDataSource();dataSource.setUser(user);dataSource.setPassword(pwd);dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/scw_0515");dataSource.setDriverClass(dirverClass);return dataSource;}// 继承EmbeddedValueResolverAware接口// 他的实现就是直接用${db.driverClass}获取配置文件的值@Overridepublic void setEmbeddedValueResolver(StringValueResolver resolver) {this.valueResolver = resolver;dirverClass = valueResolver.resolveStringValue("${db.driverClass}");}}

相关内容

热门资讯

安卓平板windows系统ap... 你有没有发现,最近安卓平板上出现了一个新趋势?那就是越来越多的用户开始尝试将Windows系统应用到...
领克05安卓系统,智能科技与驾... 你有没有发现,现在的汽车越来越智能了?这不,最近我试驾了一款叫做领克05的车型,它搭载的安卓系统简直...
安卓手机都有双系统吗,安卓手机... 你有没有想过,你的安卓手机是不是也有双系统呢?这可不是什么科幻小说里的情节,而是现实中许多手机用户都...
名爵zs安卓9.0系统,驾驭未... 你有没有听说最近名爵zs的新鲜事儿?没错,就是那个升级到了安卓9.0系统的名爵zs!哎呀呀,这可真是...
安卓车载系统哪家好用点,安卓车... 你有没有发现,随着科技的发展,汽车已经不仅仅是一个代步工具了,它更像是一个移动的智能生活空间。而在这...
安吉达订餐系统安卓下载 你有没有想过,点外卖也能变得如此轻松有趣?没错,就是那个让你在手机上就能轻松订餐的神奇工具——安吉达...
智能安卓点歌系统价格 你有没有想过,在一场热闹的聚会中,点歌环节竟然也能变得如此智能和便捷?没错,就是那个神奇的智能安卓点...
安卓系统的勿扰权限,智能守护您... 你有没有发现,手机里的安卓系统越来越智能了?不过,有时候它也会让人有点头疼,比如那个让人又爱又恨的“...
安卓系统比较好的,卓越性能与丰... 你有没有发现,现在手机市场上安卓系统简直成了香饽饽?不管是年轻人还是老年人,都对安卓手机爱不释手。今...
安卓系统文件夹名称,揭秘隐藏文... 你有没有发现,每次打开安卓手机,里面那些文件夹的名称都那么有趣,有时候甚至让人猜不透它们到底藏着什么...
安卓系统电视应用未安装,安卓电... 你有没有遇到过这种情况?家里的安卓系统电视上突然有个应用没安装,让你心里直痒痒,想赶紧弄明白怎么解决...
安卓系统投影电脑桌面,电脑桌面... 你有没有想过,你的安卓手机里的精彩内容,竟然可以无缝地投影到电脑桌面上?是的,你没有听错,这就是我们...
安卓系统老是多出照片,揭秘多出... 手机里的照片越来越多,是不是你也遇到了安卓系统里照片层出不穷的问题呢?这可真是让人头疼啊!今天,就让...
安卓12系统侧边小图标 你有没有发现,最近你的安卓手机是不是悄悄地变了个样?没错,就是那个一直默默无闻的侧边小图标,它现在可...
词典笔安卓系统如何升级,词典笔... 你有没有发现,你的词典笔安卓系统突然有点卡卡的呢?别急,别急,今天就来教你怎么给它来个焕然一新的升级...
手机系统安卓10彩蛋,体验科技... 你知道吗?在手机世界里,安卓10系统可是隐藏着不少小秘密哦!今天,就让我带你一起探索安卓10系统中的...
鸿蒙系统也兼容安卓软件,开启跨... 你知道吗?最近科技圈可是炸开了锅,因为华为的鸿蒙系统竟然宣布了一个让人眼前一亮的消息——它要兼容安卓...
澎湃安卓系统怎么样 澎湃安卓系统怎么样?亲爱的读者们,你是否在寻找一款与众不同的安卓系统?如果你对现有的安卓系统有些许厌...
华为安卓套壳系统 你知道吗?最近科技圈里有个大新闻,那就是华为安卓套壳系统的诞生。这可是个让人眼前一亮的技术突破,咱们...
自动接听电话安卓系统,安卓系统... 你有没有想过,当你的手机突然响起,而你正忙得不可开交的时候,如果能有个小助手自动接听电话,那该有多方...