Spring注解驱动开发之常用注解案例
文章目录
- Spring注解驱动开发之常用注解案例
- [1. 组件注册注解](#1. 组件注册注解)
-
- [1.1 @Configuration和@Bean注解](#1.1 @Configuration和@Bean注解)
- [1.2 自动扫描组件和指定扫描规则](#1.2 自动扫描组件和指定扫描规则)
- [1.3 自定义TypeFilter指定过滤规则](#1.3 自定义TypeFilter指定过滤规则)
- [1.4 @Scope设置组件的作用域](#1.4 @Scope设置组件的作用域)
- [1.5 @Lazy注解,bean懒加载注解](#1.5 @Lazy注解,bean懒加载注解)
- [1.6 @Conditional-按照条件注册bean](#1.6 @Conditional-按照条件注册bean)
- [2. 给容器中注册组件的方式](#2. 给容器中注册组件的方式)
-
- [2.1 包扫描+组件标注注解](#2.1 包扫描+组件标注注解)
- [2.2 @Bean](#2.2 @Bean)
- [2.3 @Import[快速给容器中导入一个组件]](#2.3 @Import[快速给容器中导入一个组件])
-
- [2.3.1 @Import(要导入到容器中的组件)](#2.3.1 @Import(要导入到容器中的组件))
- [2.3.2 ImportSelector:返回需要导入的组件的全类名数组;](#2.3.2 ImportSelector:返回需要导入的组件的全类名数组;)
- [2.3.3 ImportBeanDefinitionRegistrar:手动注册bean到容器中](#2.3.3 ImportBeanDefinitionRegistrar:手动注册bean到容器中)
- [3.使用Spring提供的 FactoryBean(工厂Bean);](#3.使用Spring提供的 FactoryBean(工厂Bean);)
-
- [3.1 默认获取到的是工厂bean调用getObject创建的对象](#3.1 默认获取到的是工厂bean调用getObject创建的对象)
- [3.2 要获取工厂Bean本身,要获取工厂Bean本身,我们需要给id前面加一个&,如:&colorFactoryBean](#3.2 要获取工厂Bean本身,要获取工厂Bean本身,我们需要给id前面加一个&,如:&colorFactoryBean)
注解驱动开发就是不再使用Spring的bean.xml文件,改为纯使用注解的方式开发
1. 组件注册注解
1.1 @Configuration和@Bean注解
-
@Configuration
此注解为配置类注解,相当于spring.xml文件,即配置类==配置文件
-
@Bean
给容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id
- 示例
java
package com.yuan.annotation.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import com.yuan.annotation.bean.Person;
//配置类==配置文件
@Configuration //告诉Spring这是一个配置类
public class MainConfig {
//给容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id
@Bean("person")
public Person personA() {
return new Person(1,"张三",33);
}
}
Person类(后续注解配置类中都会以此类举例),Person.java
java
package com.yuan.annotation.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
@NoArgsConstructor
@AllArgsConstructor
@Data
@ToString
public class Person {
private Integer id;
private String name;
private Integer age;
}
测试类
java
package com.yuan.annotation;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.yuan.annotation.bean.Person;
import com.yuan.annotation.config.MainConfig;
public class MainTest {
private static ApplicationContext applicationContext;
public static void main(String[] args) {
applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
/*
* Person person = applicationContext.getBean(Person.class);
* System.out.println(person);
*/
String [] nameTypes = applicationContext.getBeanNamesForType(Person.class);
for(String s : nameTypes) {
System.out.println(s);
}
Person person = (Person) applicationContext.getBean("person");
System.out.println(person);
}
}
1.2 自动扫描组件和指定扫描规则
- @ComponentScan 自动扫描组件注解,jdk8+版本,此注解可以在同一个类上多写几次,jdk8以下版本可以使用@ComponentScans注解
jdk8+版本示例
java
//配置类==配置文件
@Configuration //告诉Spring这是一个配置类
@ComponentScan(value = "com.yuan.annotation",includeFilters= {
@Filter(type = FilterType.ANNOTATION,classes = {Controller.class})
},useDefaultFilters=false) //指定要扫描的包
@ComponentScan(.....)
@ComponentScan(.....)
@ComponentScans(value = { @ComponentScan(value="xx.xxx") })
public class MainConfig {
//给容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id
@Bean("person")
public Person personA() {
return new Person(1,"张三",33);
}
}
jdk8以下版本示例
java
//配置类==配置文件
@Configuration //告诉Spring这是一个配置类
@ComponentScans(value = { @ComponentScan(value="xx.xxx") })
public class MainConfig {
...
}
-
value:数组类型,指定要扫描的包
-
includeFilters:Filter数组类型,指定扫描时包含哪些组件,使用此属性时,@ComponentScan的useDefaultFilters属性值设置false才能起作用,即useDefaultFilters=false;useDefaultFilters=true为默认值,扫描所有
-
excludeFilters:Filter数组类型,指定扫描时排除哪些组件
java
package com.yuan.annotation.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
import org.springframework.context.annotation.ComponentScan.Filter;
import com.yuan.annotation.bean.Person;
//配置类==配置文件
@Configuration //告诉Spring这是一个配置类
//@ComponentScan(value= {"com.yuan.annotation.bean","com.yuan.annotation.dao","com.yuan.annotation.service"})
@ComponentScan(value = "com.yuan.annotation",includeFilters= {
@Filter(type = FilterType.ANNOTATION,classes = Controller.class)
}) //指定要扫描的包
public class MainConfig {
//给容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id
@Bean("person")
public Person personA() {
return new Person(1,"张三",33);
}
}
1.3 自定义TypeFilter指定过滤规则
- FilterType.ANNOTATION:按照注解(常用)
- FilterType.ASSIGNABLE_TYPE:按照指定的类型(常用)
- FilterType.ASPECTJ:使用ASPECTJ表达式
- FilterType.CUSTOM:使用用户自定义规则
- FilterType.REGEX:使用正则表达式
- 自定义规则类,如:MyTypeFilter.java
- 自定义过滤规则类需要实现TypeFilter接口
java
package com.yuan.annotation.config;
import java.io.IOException;
import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;
public class MyTypeFilter implements TypeFilter {
/*
* metadataReader:读取到的当前正在扫描的类
* metadataReaderFactory:可以获取到其他任何类信息的
*/
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
throws IOException {
//获取当前类注解的信息
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
//获取当前正在扫描的类的信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
//获取当前类资源(类的路径)
Resource resource = metadataReader.getResource();
String className = classMetadata.getClassName();
System.out.println("--->"+className);
//如果className中包含er,表示匹配成功
if(className.contains("er")) {
return true;
}
return false;
}
}
- 配置类,MainConfig.java
java
package com.yuan.annotation.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.ComponentScans;
import com.yuan.annotation.bean.Person;
import com.yuan.annotation.service.BookService;
//配置类==配置文件
@Configuration //告诉Spring这是一个配置类
@ComponentScan(value = "com.yuan.annotation",includeFilters= {
@Filter(type = FilterType.CUSTOM,classes = {MyTypeFilter.class})
},useDefaultFilters=false) //指定要扫描的包
@ComponentScans(value = { @ComponentScan(value="xx.xxx") })
public class MainConfig {
//给容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id
@Bean("person")
public Person personA() {
return new Person(1,"张三",33);
}
}
- 测试类IOCTest.java
java
package com.yuan.annotation.test;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.yuan.annotation.config.MainConfig;
public class IOCTest {
private AnnotationConfigApplicationContext applicationContext;
@Test
public void test01() {
applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
String [] definitionNames = applicationContext.getBeanDefinitionNames();
for(String beanName : definitionNames) {
System.out.println(beanName);
}
}
}
- 打印结果:
java
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
person
myTypeFilter
bookController
bookService
1.4 @Scope设置组件的作用域
- 配置类,ScopeConfig.java
java
package com.yuan.annotation.config;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import com.yuan.annotation.bean.Person;
@Configuration
public class ScopeConfig {
/**
* @see ConfigurableBeanFactory#SCOPE_PROTOTYPE
* @see ConfigurableBeanFactory#SCOPE_SINGLETON
* @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST
* @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION
*
* singleton: 单实例(默认),IOC容器启动时会调用方法创建对象放到IOC容器中
* prototype: 多实例的,IOC启动时不会去调用方法创建对象放在容器中,每次获取的时候才会调用方法创建对象
* request: 同一次请求创建一个实例
* session: 同一次会话创建一个实例
*
*/
@Scope("prototype")
@Bean("person")
public Person person() {
System.out.println("给容器中添加Person对象....");
return new Person(1,"张三",22);
}
}
- 测试类,IOCTest.java
java
package com.yuan.annotation.test;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.yuan.annotation.bean.Person;
import com.yuan.annotation.config.MainConfig;
import com.yuan.annotation.config.ScopeConfig;
public class IOCTest {
private AnnotationConfigApplicationContext applicationContext;
@Test
public void test02() {
applicationContext = new AnnotationConfigApplicationContext(ScopeConfig.class);
/*
* String [] definitionNames = applicationContext.getBeanDefinitionNames();
* for(String beanName : definitionNames) { System.out.println(beanName); }
*/
//默认为单实例的
Person person = (Person) applicationContext.getBean("person");
Person person2 = (Person) applicationContext.getBean("person");
System.out.println(person == person2);
}
}
1.5 @Lazy注解,bean懒加载注解
java
package com.yuan.annotation.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import com.yuan.annotation.bean.Person;
@Configuration
public class LazConfig {
/**
* @Lazy:懒加载,针对scope为单实例的bean而言
* 单实例bean,默认容器启动的时候创建
* 懒加载:容器启动时不创建对象,第一次使用(获取)Bean对象,并初始化
* @return
*/
@Lazy
@Bean
public Person person() {
return new Person(1,"张三",22);
}
}
1.6 @Conditional-按照条件注册bean
@Conditional({Condation}) : 按照一定的条件进行判断,满足条件给容器中注册bean
案例:根据操作系统的创始人来实例对应的Person
- 需要定义两个Condition类,如LinuxCondition.java和WindowsCondition.java
-
LinuxCondition.java和WindowsCondition.java必须实现Condition接口
-
WindowsCondition.java
java
package com.yuan.annotation.condition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
/**
* 判断是否为Windows系统
* @author jinshengyuan
*
*/
public class WindowsCondition implements Condition{
/**
* ConditionContext : 判断条件能使用的上下文(环境)
* AnnotatedTypeMetadata : 注解信息
*/
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
//判断是否Linux系统
//1.能获取到IOC使用的beanFactory
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
//2.获取类加载器
ClassLoader classLoader = context.getClassLoader();
//3.获取当前环境信息
Environment environment = context.getEnvironment();
//4.获取bean定义的注册类
BeanDefinitionRegistry registry = context.getRegistry();
//可以判断容器中的bean注册情况,也可以给容器中注册bean
boolean beanDefinition = registry.containsBeanDefinition("person");
String property = environment.getProperty("os.name");
//如果property中包含Windows,则返回true
if(property.contains("Windows")) {
return true;
}
return false;
}
}
- LinuxCondition.java
java
package com.yuan.annotation.condition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
/**
* 判断是否为Linux系统
* @author jinshengyuan
*
*/
public class LinuxCondition implements Condition {
/**
* ConditionContext : 判断条件能使用的上下文(环境)
* AnnotatedTypeMetadata : 注解信息
*/
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
//判断是否Linux系统
//1.能获取到IOC使用的beanFactory
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
//2.获取类加载器
ClassLoader classLoader = context.getClassLoader();
//3.获取当前环境信息
Environment environment = context.getEnvironment();
//4.获取bean定义的注册类
BeanDefinitionRegistry registry = context.getRegistry();
//可以判断容器中的bean注册情况,也可以给容器中注册bean
boolean beanDefinition = registry.containsBeanDefinition("person");
String property = environment.getProperty("os.name");
//如果property中包含Linux,则返回true
if(property.contains("Linux")) {
return true;
}
return false;
}
}
- @Conditional注解配置类
java
package com.yuan.annotation.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import com.yuan.annotation.bean.Person;
import com.yuan.annotation.condition.LinuxCondition;
import com.yuan.annotation.condition.WindowsCondition;
@Configuration
public class ConditionalConfig {
/**
* @Conditional({Condation}) : 按照一定的条件进行判断,满足条件给容器中注册bean
* @Conditional可以标注在类上,也可以标注在方法上
* 标注在类上:类中组件统一设置,满足当前条件,这个类中配置的所有bean才能生效
* 需求:
* 如果系统是Windows,给容器中注册("bill")
* 如果是Linux系统,给容器中注册("linus")
*/
//如果为Windows系统则实例化bill类
@Conditional({WindowsCondition.class})
@Bean("bill")
public Person person() {
return new Person(1,"Bill Gates",65);
}
//如果为Linx系统则实例化linus类
@Conditional({LinuxCondition.class})
@Bean("linus")
public Person person1() {
return new Person(1,"linus",48);
}
}
- 测试类
java
package com.yuan.annotation.test;
import java.util.Map;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import com.yuan.annotation.bean.Person;
import com.yuan.annotation.config.ConditionalConfig;
import com.yuan.annotation.config.MainConfig;
import com.yuan.annotation.config.ScopeConfig;
public class IOCTest {
private AnnotationConfigApplicationContext applicationContext;
@Test
public void test03() {
applicationContext = new AnnotationConfigApplicationContext(ConditionalConfig.class);
ConfigurableEnvironment environment = applicationContext.getEnvironment();
//动态获取环境变量的值:Windows 10
String osName = environment.getProperty("os.name");
System.out.println(osName);
//获取已定义的bean
String [] definitionNames = applicationContext.getBeanDefinitionNames();
for(String beanName : definitionNames) {
System.out.println(beanName);
}
Map<String, Person> map = applicationContext.getBeansOfType(Person.class);
System.out.println(map);
}
}
- 输出结果
由于是Windows 10,则只有bill类被实例化
tex
Windows 10
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
conditionalConfig
bill
{bill=Person(id=1, name=Bill Gates, age=65)}
2. 给容器中注册组件的方式
2.1 包扫描+组件标注注解
@Controller/@Service/@Repository/@Component)[只适用于自己写的类]
2.2 @Bean
[导入的第三方包里面的组件]
2.3 @Import[快速给容器中导入一个组件]
2.3.1 @Import(要导入到容器中的组件)
容器中就会自动注册这个组件,id默认是全类名(如下面的com.yuan.bean.Color)
- 定义一个Color.java类
java
package com.yuan.bean;
/**
* color 类
*/
public class Color {
}
- 在ColorMainConfig.java中使用@Import注解向容器中注入Color类
java
package com.yuan.config;
import com.yuan.bean.Color;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* @Author: Jinsheng·yuan
* @CreateDate: 2020/1/14 21:59
* @Description: 使用@Import 注册组件
*/
@Configuration
@Import(Color.class) //注入单个组件
//@Import({Color.class,Red.class}) //注入多个组件
public class ColorMainConfig {
}
- 单元测试
java
package com.yuan.test;
import com.yuan.config.ColorMainConfig;
import com.yuan.config.MainConfig;
import com.yuan.config.MyConfigTwo;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* @Author: Jinsheng·yuan
* @CreateDate: 2020/1/14 21:59
* @Description: 使用@Import 注册组件
*/
public class IOCTest {
private AnnotationConfigApplicationContext applicationContext;
/**
* 使用@Import注解向容器注入组件测试
*/
@Test
public void testImport(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ColorMainConfig.class);
printBeans(applicationContext);
}
/**
* 打印IOC中注入的所有组件
* @param applicationContext
*/
public void printBeans(AnnotationConfigApplicationContext applicationContext ){
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
}
}
- 测试打印结果
tex
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
colorMainConfig #自定义配置类bean
com.yuan.bean.Color #注入组件(bean)的全类名
2.3.2 ImportSelector:返回需要导入的组件的全类名数组;
- 自定义逻辑返回要导入的组件,需要实现ImportSelector接口,结合@Import注解一起使用
- 自定义MyImportSelector.java
java
package com.yuan.condition;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
/**
* @Author: Jinsheng·yuan
* @CreateDate: 2020/1/14 22:15
* @Description: 实现ImportSelector接口来自定义逻辑返回要导入的组件
*/
public class MyImportSelector implements ImportSelector {
/**
*
* @param importingClassMetadata 当前标注@Import注解的类的所有注解信息
* @return 返回值就是导入容器中的组件的全类名
*/
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
//可获取标注@Import注解类的所有注解信息
System.out.println("importingClassMetadata.getClassName():"+importingClassMetadata.getClassName());
System.out.println("importingClassMetadata.getAnnotations():"+importingClassMetadata.getAnnotations());
//return new String[0]; //这里不能返回null,可以返回一个空数组
return new String[]{"com.yuan.bean.Blue","com.yuan.bean.Yellow"};//导入容器中的组件的全类名
}
}
- 配置类
java
package com.yuan.config;
import com.yuan.bean.Color;
import com.yuan.condition.MyImportSelector;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* @Author: Jinsheng·yuan
* @CreateDate: 2020/1/14 21:59
* @Description: 使用@Import 注册组件
*/
@Configuration
@Import({Color.class, MyImportSelector.class})
public class ColorMainConfig {
}
- IOCTest.java测试结果
tex
mportingClassMetadata.getClassName():com.yuan.config.ColorMainConfig
importingClassMetadata.getAnnotations():org.springframework.core.annotation.TypeMappedAnnotations@36b4fe2a
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
colorMainConfig
com.yuan.bean.Color
com.yuan.bean.Blue
com.yuan.bean.Yellow
2.3.3 ImportBeanDefinitionRegistrar:手动注册bean到容器中
通过实现ImportBeanDefinitionRegistrar接口,手动注册bean到容器中,需要结合**@Import注解使用**
- MyImportBeanDefinitionRegistrar.java
java
package com.yuan.condition;
import com.yuan.bean.Student;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
/**
* @Author: Jinsheng·yuan
* @CreateDate: 2020/1/14 22:48
* @Description: 通过实现ImportBeanDefinitionRegistrar接口,手动注册bean到容器中
*/
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
/**
*
* @param importingClassMetadata 当前类的注解信息
* @param registry BeanDefinition注册类
* @param importBeanNameGenerator
*/
/* @Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) {
//此方法还未理解透
}*/
/**
*
* @param importingClassMetadata 当前类的注解信息
* @param registry BeanDefinition注册类,
* 把所有需要添加到容器中的Bean,用 registry.registerBeanDefinition()手工注册进来
*
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//registry.registerBeanDefinition();
boolean red = registry.containsBeanDefinition("com.yuan.bean.Red");
boolean blue = registry.containsBeanDefinition("com.yuan.bean.Blue");
//如果存在Red与Blue类,则注册自定义的student类
if(red && blue){
//指定bean的定义信息(就是Bean的类型)
RootBeanDefinition beanDefinition = new RootBeanDefinition(Student.class);
//自定义bean的名字为student
registry.registerBeanDefinition("student",beanDefinition);
}
}
}
- 配置类ColorMainConfig.java
java
package com.yuan.config;
import com.yuan.bean.Color;
import com.yuan.bean.Red;
import com.yuan.condition.MyImportBeanDefinitionRegistrar;
import com.yuan.condition.MyImportSelector;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import javax.swing.text.rtf.RTFEditorKit;
/**
* @Author: Jinsheng·yuan
* @CreateDate: 2020/1/14 21:59
* @Description: 使用@Import 注册组件
*/
@Configuration
@Import({Color.class, Red.class,MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class ColorMainConfig {
}
- 测试结果
tex
importingClassMetadata.getClassName():com.yuan.config.ColorMainConfig
importingClassMetadata.getAnnotations():org.springframework.core.annotation.TypeMappedAnnotations@574b560f
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
colorMainConfig
com.yuan.bean.Color
com.yuan.bean.Red
com.yuan.bean.Blue
com.yuan.bean.Yellow
student #手工注册到容器的bean
3.使用Spring提供的 FactoryBean(工厂Bean);
3.1 默认获取到的是工厂bean调用getObject创建的对象
3.2 要获取工厂Bean本身,要获取工厂Bean本身,我们需要给id前面加一个&,如:&colorFactoryBean
- 自定义ColorFactorBean.java,实现FactoryBean接口
java
package com.yuan.bean;
import org.springframework.beans.factory.FactoryBean;
/**
* @Author: Jinsheng·yuan
* @CreateDate: 2020/1/14 23:15
* @Description: 创建一个Spring定义的FactoryBean
*/
public class ColorFactorBean implements FactoryBean<Color> {
/**
* 是单例么?
* true:是,这个bean在容器中只会保留一份;
* false: 多实例,每次都会创建一个新的bean
* @return
*/
@Override
public boolean isSingleton() {
return false;
}
/**
*
* @return
* @throws Exception
*/
@Override
public Color getObject() throws Exception {
return new Color();
}
/**
* 返回一个Color对象,这个对象会创建到容器中
* @return
*/
@Override
public Class<?> getObjectType() {
return Color.class;
}
}
- 主配置类中注册ColorFactorBean
java
package com.yuan.config;
import com.yuan.bean.Color;
import com.yuan.bean.ColorFactorBean;
import com.yuan.bean.Red;
import com.yuan.condition.MyImportBeanDefinitionRegistrar;
import com.yuan.condition.MyImportSelector;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import javax.swing.text.rtf.RTFEditorKit;
/**
* @Author: Jinsheng·yuan
* @CreateDate: 2020/1/14 21:59
* @Description: 使用@Import 注册组件
*/
@Configuration
@Import({Color.class, Red.class,MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class ColorMainConfig {
/**
* 注入ColorFactorBean对象
* @return
*/
@Bean
public ColorFactorBean colorFactorBean(){
return new ColorFactorBean();
}
}
- 测试
java
package com.yuan.test;
import com.yuan.config.ColorMainConfig;
import com.yuan.config.MainConfig;
import com.yuan.config.MyConfigTwo;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* @Author: Jinsheng·yuan
* @CreateDate: 2020/1/14 21:59
* @Description: 使用@Import 注册组件
*/
public class IOCTest {
private AnnotationConfigApplicationContext applicationContext;
/**
* 使用@Import注解向容器注入组件测试
*/
@Test
public void testImport(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ColorMainConfig.class);
Object colorFactorBean = applicationContext.getBean("colorFactorBean");
Object colorFactorBean1 = applicationContext.getBean("colorFactorBean");
System.out.println(colorFactorBean == colorFactorBean1); //是否为同意对象
//1. 获取Bean的类型,默认获取的的是工厂bean调用 getObject()对象创建的bean,如下获取的为:com.yuan.bean.Color
System.out.println("colorFactorBean的类型:"+colorFactorBean.getClass());
//2. 若要获取工厂bean本身,则需要给bean的id前面加一个 & ,如&colorFactorBean
Object factoryBean = applicationContext.getBean("&colorFactorBean");
System.out.println("colorFactorBean本身的类型:"+factoryBean.getClass());
printBeans(applicationContext);
}
/**
* 打印IOC中注入的所有组件
* @param applicationContext
*/
public void printBeans(AnnotationConfigApplicationContext applicationContext ){
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
}
}
- 测试结果
tex
importingClassMetadata.getClassName():com.yuan.config.ColorMainConfig
importingClassMetadata.getAnnotations():org.springframework.core.annotation.TypeMappedAnnotations@574b560f
false
colorFactorBean的类型:class com.yuan.bean.Color
colorFactorBean本身的类型:class com.yuan.bean.ColorFactorBean
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
colorMainConfig
com.yuan.bean.Color
com.yuan.bean.Red
com.yuan.bean.Blue
com.yuan.bean.Yellow
colorFactorBean
student