本文最后更新于:June 14, 2022 pm
Spring 是目前主流的 Java Web 开发框架,是 Java 世界最为成功的框架。Spring框架是由于软件开发的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中受益。该框架是一个轻量级的开源框架,具有很高的凝聚力和吸引力。Spring 框架不局限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何 Java 应用都可以从 Spring 中受益。Spring 框架还是一个超级粘合平台,除了自己提供功能外,还提供粘合其他技术和框架的能力。
目录 导入普通类 目标类:(只是一个普通的类)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package com.SpringTestAnnotation.TestValue;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import javax.annotation.Resource;public class Per { public void show () { System.out.println("Per show" ); } }
配置类中进行导入:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package com.SpringTestAnnotation;import com.SpringTestAnnotation.TestValue.OrderS;import com.SpringTestAnnotation.TestValue.OurAnno;import com.SpringTestAnnotation.TestValue.Per;import org.springframework.beans.factory.annotation.Autowire;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.*;import org.springframework.stereotype.Component;@ComponentScan(value = "com.SpringTestAnnotation") @Import(Per.class) public class TestConfig { }
测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package com.SpringTestAnnotation;import com.SpringTestAnnotation.TestValue.OrderS;import com.SpringTestAnnotation.TestValue.Per;import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class TestAnnotation { public static void main (String[] args) { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(TestConfig.class); Per per = applicationContext.getBean(Per.class); per.show(); } }
需要说明的一点,使用@Import导入的类的Bean名称不是类名的小驼峰(类首字母小写),也就是说不是使用注解时的名称。如类名为OrderS,使用注解为orderS;而使用@Import就不再是orderS了,内部会自动生成一个名称。所以这里并没有直接使用名称进行获取,而是通过class获取的。
输出结果:
如果在配置类中没有导入目标类,则会报错如下:
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.SpringTestAnnotation.TestValue.Per' available
📢注意:使用@Import导入的类并不是一个普通的Bean,而是一个配置Bean。在配置Bean中可以使用@Bean定义其他的Bean,以及可以在配置Bean中使用@ComponentScan。
ImportSelector
个人理解:可以动态批量注入Bean。
目标类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package com.SpringTestAnnotation.TestValue;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.ComponentScan;import org.springframework.stereotype.Component;import javax.annotation.Resource;public class Per { public void show () { System.out.println("Per show" ); } }
实现接口ImportSelector:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package com.SpringTestAnnotation.TestValue;import org.springframework.context.annotation.ImportSelector;import org.springframework.core.type.AnnotationMetadata;import org.springframework.stereotype.Component;public class OrderS implements ImportSelector { @Override public String[] selectImports(AnnotationMetadata annotationMetadata) { return new String[]{Per.class.getName()}; } }
实现接口的类必须成为一个配置Bean,所以使用@Import将其设置为一个配置Bean:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package com.SpringTestAnnotation;import com.SpringTestAnnotation.TestValue.OrderS;import com.SpringTestAnnotation.TestValue.OurAnno;import com.SpringTestAnnotation.TestValue.Per;import org.springframework.beans.factory.annotation.Autowire;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.*;import org.springframework.stereotype.Component;@ComponentScan(value = "com.SpringTestAnnotation") @Import(OrderS.class) public class TestConfig { }
测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package com.SpringTestAnnotation;import com.SpringTestAnnotation.TestValue.OrderS;import com.SpringTestAnnotation.TestValue.Per;import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class TestAnnotation { public static void main (String[] args) { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(TestConfig.class); Per per = applicationContext.getBean(Per.class); per.show(); } }
获取Bean也不能使用名称进行获取,而是通过class获取。
输出结果:
如果不在配置类中使用@Import,而是直接使用@Component,则会报错如下:
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.SpringTestAnnotation.TestValue.Per' available
ImportBeanDefinitionRegistrar 和上面的接口是一样的功能。
其他代码同上,只是修改以下实现的接口。上面接口的实现改成新接口:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package com.SpringTestAnnotation.TestValue;import org.springframework.beans.factory.support.AbstractBeanDefinition;import org.springframework.beans.factory.support.BeanDefinitionBuilder;import org.springframework.beans.factory.support.BeanDefinitionRegistry;import org.springframework.beans.factory.support.BeanNameGenerator;import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;import org.springframework.context.annotation.ImportSelector;import org.springframework.core.type.AnnotationMetadata;import org.springframework.stereotype.Component;public class OrderS implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions (AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) { BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(); AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition(); beanDefinition.setBeanClass(Per.class); registry.registerBeanDefinition("per123" ,beanDefinition); } }
测试输出结果:
然后再通过名称进行获取:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package com.SpringTestAnnotation;import com.SpringTestAnnotation.TestValue.OrderS;import com.SpringTestAnnotation.TestValue.Per;import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class TestAnnotation { public static void main (String[] args) { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(TestConfig.class); Per per = applicationContext.getBean("per123" ,Per.class); per.show(); } }
其中的per123
为实现接口时的自定义Bean名称。输出结果同上。