Spring Import注解
今天了解了,Spring @Import的使用
先贴上Spring官方关于Spring @Import注解的文档链接 https://docs.spring.io/spring/docs/3.0.x/spring-framework-reference/html/beans.html#beans-java-using-import
一.@Import 引入一个普通java对象 适用4.2.0之后版本
三.@Import 与 ImportBeanDefinitionRegistrar 使用4.2.0之前版本
四.@Import 与 ImportSelector 使用方式
一。@Import直接引入一个类,将其作为Spring bean,受Spring容器管理;(Spring 4.2.0以及之后版本可以使用)
在Spring 4.2.x之前的版本,@Import注解无法引入一个没有注解 @Configuration 或者 @Bean 且没有实现ImportBeanDefinitionRegistry 或者 ImportSelector 的类,将其作为Spring Bean管理;
如果你在使用的版本是4.2.0之前的版本,想要使用@Import导入一个类,方法二、三或许可行;
特地拿了Spring 4.1.9版本,测试,@Import一个普通的Java类,抛出异常:
Exception in thread "main" org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: pack1.AppConfig2 was @Import'ed but is not annotated with @Configuration nor does it declare any @Bean methods; it does not implement ImportSelector or extend ImportBeanDefinitionRegistrar. Update the class to meet one of these requirements or do not attempt to @Import it.
翻译过来就是: AppConfig2被import导入了,但是没有标注@Configuration或者也没有声明任何@Bean方法,也没有实现ImportSelector或者继承ImportBeanDefinitionRegistrar类;
不做任何改动,修改maven导入的Spring版本号,拿4.2.0测试,就成功Import该java类; Import导入的类,默认beanId是类全限定名,可以设定@Configuration改变类的beanId;
关于为什么配置类上加@Configuration作用,查看我的理解 https://www.cnblogs.com/lvbinbin2yujie/p/10279416.html
@Configuration
@Import({AppConfig2.class})
public class AppConfig1 { public static void main(String[] args) {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig1.class);
String[] names = ac.getBeanDefinitionNames();
for (String string : names) {
System.out.println(string+","+ac.getBean(string));
}
}
} public class AppConfig2 { }
二。@Import引入配置类@Configuration标注的类; 纯属个人看Spring官方文档的理解,大致能看懂,Spring官方文档链接:https://docs.spring.io/spring/docs/3.0.x/spring-framework-reference/html/beans.html#beans-java-using-import
2.1 先说最容易看懂的一种使用方式,每个@Configuration里的@Bean定义都很明显,就像开发过程中写了好多配置文件,然后在某一个XML里面<import />其他的bean;
@Configuration
public class ConfigA { @Bean
public A a() {
return new A();
}
} public class A { }
@Import({ConfigA.class})
@Configuration
public class ConfigB {
@Bean
public B b() {
return new B();
}
public static void main(String[] args) {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(ConfigB.class);
String[] names = ac.getBeanDefinitionNames();
for (String string : names) {
System.out.println(string+" , "+ac.getBean(string));
}
}
}
测试结果如下: 印证了 1. @Import引入的类默认beanId为类全路径名 ; 2. @Configuration标注的类是动态代理之后的类 ;
configB , pack1.ConfigB$$EnhancerBySpringCGLIB$$1acf4932@4313f5bc
pack1.ConfigA , pack1.ConfigA$$EnhancerBySpringCGLIB$$e26ca611@7f010382
a , pack1.A@1e802ef9
b , pack1.B@2b6faea6
2.2 但是我们平常见得开发中,比如service配置文件在一个XML里,dao的配置文件在一个XML中,就会跨文件引用,但是我们都会写 ref引用那个对象,因为Spring会帮助我们找到需要的对象;
举个例子模拟这种跨文件的引用,Spring官方文档里面也有这样一个例子;
// dao类
public class AccountDao { private DataSource dataSource; public AccountDao(DataSource dataSource) {
this.dataSource=dataSource;
} public void saveMoney() {
System.out.println("利用dataSource模拟存钱操作");
} }
// service类
public class AccountService { private AccountDao accountDao; public AccountService(AccountDao accountDao) {
this.accountDao=accountDao;
} public void saveMoney() {
accountDao.saveMoney();
}
}
下面将使用注解,来代替原来的XML配置方式,定义了两个配置类DaoConfig ServiceConfig
@Configuration
public class DaoConfig { @Autowired
private DataSource dataSource; @Bean
public AccountDao accountDao() {
return new AccountDao(dataSource);
}
}
@Configuration
public class ServiceConfig { @Autowired
private AccountDao accountDao; @Bean
public AccountService accountService() {
return new AccountService(accountDao);
}
@Configuration
@Import({ServiceConfig.class,DaoConfig.class})
public class SystemConfig { @Bean
public DataSource dataSource() {
return new DruidDataSource();
} public static void main(String[] args) {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SystemConfig.class);
AccountService service = ac.getBean(AccountService.class);
service.saveMoney();
}
}
查看测试结果:
利用dataSource模拟存钱操作
简单来讲下我的分析:从bean的load讲一下, 第一个加载的bean是SystemConfig,先解析Import注解,和SysemConfig一样递归加载ServiceConfig以及DaoConfig这两个类,递归因为没有别的注解了,所以就是解析@Bean,也就是纳入了AccountService 、AccountDao 最后是 DataSource 这三个Bean ,别忘了 加上SystemConfig、ServiceConfig 、DaoConfig这样六个bean对象;然后属性@Autowired注入,如果属性注入的时候这个bean还没有就回去实例化这个Bean,这样一来就完成了。
可能看完这个方法,还是复杂啊,假如少Import一个配置类,那肯定会报错了。
2.3 此外,Spring另外一个方法可以实现上面功能,比较奇特的方式;
@Configuration
public class DaoConfig { @Autowired
private DataSource dataSource; @Bean
public AccountDao accountDao() {
return new AccountDao(dataSource);
}
}
@Configuration
public class ServiceConfig2 { @Autowired
private DaoConfig daoConfig; @Bean
public AccountService accountService() {
AccountDao dao1 = daoConfig.accountDao();
System.out.println("ServiceConfig中的dao:"+dao1);
return new AccountService(dao1);
}
}
@Configuration
@Import({ServiceConfig2.class,DaoConfig.class})
public class SystemConfig2 { @Autowired
private ServiceConfig2 serviceConfig; @Bean
public DataSource dataSource() {
return new DruidDataSource();
} public static void main(String[] args) {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SystemConfig2.class);
AccountService service = ac.getBean(AccountService.class);
service.saveMoney();
}
}
测试结果: 由于使用main方法测试,如果在业务方法中可以直接 serviceConfig.accountService().saveMoney();
ServiceConfig中的dao:pack2.AccountDao@3daa422a
利用dataSource模拟存钱操作
说明: 1. @Configuration注解的类本身也是个bean对象,这点不能忘; 2.@Configuration标注的类调用 同一个@Bean方法 会一直得到同一个bean对象 ;
3. Spring官方文档中有一句:要使用@Configuration注解需要使用 <context:component-scan /> 标签
三。方法三,实现ImportBeanDefinitionRegistrar接口, 这也是 Spring 4.2.0之前版本 如果想要引入一个普通bean,没法直接Import,实现接口并且重写方法里注册这个bean对象;
public class ABeanDefinitionRegistry implements ImportBeanDefinitionRegistrar{
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry) {
//简单说下使用,只要将beanDefinition注册到registry里,就算把bean对象引入了;只是简单写了个例子引入A类
BeanDefinitionBuilder bd = BeanDefinitionBuilder.rootBeanDefinition(A.class);
registry.registerBeanDefinition("a", bd.getBeanDefinition());
}
}
@Import({ABeanDefinitionRegistry.class})
这个方法是怎么调用的呢?ConfigurationClassParser类的processImports方法,是解析类上@Import注解的;ConfigurationClassBeanDefinitionReader的loadBeanDefinitionsFromRegistrars方法,遍历引入的实现ImportBeanDefinitionRegistrar的类,然后调用其registerBeanDefinitions方法;
四。方法四,实现ImportSelector接口,这种方式相比之前方式更加容易理解,只需要返回bean的类全限定名即可;
public class AImportSelector implements ImportSelector{
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[] {A.class.getName()};
}
}
这样调用即可;
@Import({AImportSelector.class})
三、四两种方式都有个参数为AnnotationMetadata是类上的注解信息的,可以这样实现很多功能,由于不是很了解;

Spring Import注解的更多相关文章
- Spring @Import注解源码解析
简介 Spring 3.0之前,创建Bean可以通过xml配置文件与扫描特定包下面的类来将类注入到Spring IOC容器内.而在Spring 3.0之后提供了JavaConfig的方式,也就是将IO ...
- Spring @Import 注解
@Import 导入某个bean 文件 @Configuration @Import({User.class,MyImportSelector.class,MyImportBeanDefinitio ...
- Spring @Import注解 —— 导入资源
在应用中,有时没有把某个类注入到IOC容器中,但在运用的时候需要获取该类对应的bean,此时就需要用到@Import注解.示例如下: 先创建两个类,不用注解注入到IOC容器中,在应用的时候在导入到当前 ...
- Spring框架中的org.springframework.context.annotation.Import注解类
@Import注解的作用和在使用spring的xml配置时用到的<import/>类似.但应注意是@Import在使用时必须要保证能被IOC容器扫描到,所以通常它会和@Configurat ...
- spring框架中的@Import注解
spring框架中的@Import注解 Spring框架中的@Import注解 在之前的文章中,作者介绍了Spring JavaConfig. 这是除了使用传统的XML文件之外,spring带来的新的 ...
- spring 中的@Import注解和@ImportResource注解
概述:@Import注解是引入带有@Configuration的java类. @ImportResource是引入spring配置文件.xml 案例的核心代码如下: package com.timo. ...
- 五、Spring中的@Import注解
一.使用@Import注解导入组件 @Import注解的作用是给容器中导入组件,回顾下我们给容器中导入组件的方式,可以通过Spring的xm配置方式,可以通过注解,如@Component等,也可以通过 ...
- spring注解之@Import注解的三种使用方式
目录 1.@Import注解须知 2.@Import的三种用法 3.@Import注解的三种使用方式总结 @ 1.@Import注解须知 1.@Import只能用在类上 ,@Import通过快速导入的 ...
- EnableAutoConfiguration注解 Spring中@Import注解的作用和使用
EnableAutoConfiguration注解 http://www.51gjie.com/javaweb/1046.html springboot@EnableAutoConfiguration ...
随机推荐
- Objective-C 对象和消息模型
Objective-C 对象模型 首先要了解一下Objective-C中关于类和对象的定义,Cocoa中大部分对象都是NSObject的子类(NSProxy是一个例外),继承了NSObject的方法. ...
- 第三天:DOM操作css
基本语法: 引用样式时是在head中,用link,另外需要<div>才能显示 修改样式:按下按钮后,引用的样式部分,颜色变为蓝色 如图下图是更改了样式中hello的颜色 代码如下: < ...
- 8.正则表达式和XPath
1.使用正则表达式爬取内涵段子 import requests import re def loadPage(page): url = "http://www.neihan8.com/art ...
- 输出的数据格式是如何决定的-------Asp.net WebAPI学习笔记(二)
在上一篇文章<路由其实也可以很简单>,我们解决了路由问题,这篇文章,我们来研究剩下的另一个问题,为何我们的方法返回的是一个列表,输出到客户端的时候,变成json呢,大家应该还记得我们上一篇 ...
- ffplay源码分析5-图像格式转换
本文为作者原创,转载请注明出处:https://www.cnblogs.com/leisure_chn/p/10311376.html ffplay是FFmpeg工程自带的简单播放器,使用FFmpeg ...
- 微服务统一登陆认证怎么做?JWT ?
无状态登录原理 1.1.什么是有状态? 有状态服务,即服务端需要记录每次会话的客户端信息,从而识别客户端身份,根据用户身份进行请求的处理,典型的设计如tomcat中的session. 例如登录:用户登 ...
- [Ynoi2018]未来日记(分块)
分块神题. 看了一会儿题解,看懂了思路,然后写了两个小时,调了一个多小时,好多地方写错了. 我们考虑对序列和值域都分块.\(sum1[i][j]\) 表示前 \(i\) 个块,第 \(j\) 块值域有 ...
- XSS 跨站脚本攻击 的防御解决方案
虽然说在某些特殊情况下依然可能会产生XSS,但是如果严格按照此解决方案则能避免大部分XSS攻击. 原则:宁死也不让数据变成可执行的代码,不信任任何用户的数据,严格区数据和代码. XSS的演示 Exam ...
- java String 内存模型
关于java的内存模型,参照以下的一篇文章: https://isudox.com/2016/06/22/memory-model-of-string-in-java-language/
- Linux - 更改软件源
镜像源 网易镜像源 在网易开源镜像页面,点击对应镜像名的使用帮助,可以查看到更新源的方法,按步骤操作即可. 阿里云镜像源 在阿里云开源镜像页面,点击对应Mirror分类的help标签,可以查看到更新源 ...