组件注册
1.@Configuration
通过@Configuration标识,告诉Spring这是一个配置类.
@Configuration //告诉spring这是一个配置类 public class MainConf { }
2.@ComponentScan
@ComponentScan这个注解通过value属性扫描所有被@Component,@Service,@Controller和@Repository标注过的类,将类放入IOC容器中
@ComponentScan可以通过includeFilters属性扫描的时候按照一定的规则排除组件;
@ComponentScan(value="com.spring",includeFilters= { @Filter(type=FilterType.ANNOTATION,classes= {Controller.class,Service.class}), @Filter(type=FilterType.ASSIGNABLE_TYPE,classes= {Service.class}), @Filter(type=FilterType.CUSTOM,classes= {MyTypeFilter.class}) },useDefaultFilters=false)
其中:
1.ANNOTATION:按照注解进行排除
2.ASSIGNABLE_TYPE:按照给定的类型进行排除
3.ASPECTJ:使用ASPECTJ表达式进行排除
4.REGEX:使用正则表达式进行排除
5.CUSTOM:自定义规则
自定义规则需要实现TypeFilter接口
public class MyTypeFilter implements TypeFilter{ /** * metadataReader,读取到当前正在扫描的类信息 * metadataReaderFactory,可以获取到其他任何类信息的 * */ @Override public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { //获取当前类注解的信息 AnnotationMetadata metadata = metadataReader.getAnnotationMetadata(); //获取当前正在扫描的类的类信息 ClassMetadata classMetadata = metadataReader.getClassMetadata(); //获取当前类的资源信息(路径) Resource resource = metadataReader.getResource(); String className = classMetadata.getClassName(); System.out.println(className); if(className.contains("er")) { return true; } return false; } }
3.@Bean
@Bean可以将组件注册到IOC容器中
public class MainConf { @Bean //注册一个bean;类型就是返回值的类型id默认方法名作为id public Person person() { return new Person("lisi", 20); } }
Person类:
public class Person { private String name; private Integer age; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]"; } public Person(String name, Integer age) { super(); this.name = name; this.age = age; } public Person() { super(); } }
4.@Import,ImportSelector和ImportBeanDefinitionRegistrar
@Import导入组件,id默认是组件的全类名
@Import({Color.class,Red.class})
ImportSelector:返回需要导入的组件的全类名数组,需要实现ImportSelector接口
//自定义逻辑返回需要导入的组件 public class MyImportSelector implements ImportSelector { //返回值,就是要导入容器中的组件类全类名 //AnnotationMetadata:当前标注@Import注解的类的所有注解信息 @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { //方法不要返回null return new String[]{"com.spring.bean.Blue","com.spring.bean.Yellow"}; } }
ImportBeanDefinitionRegistrar:手动注册到bean容器中,需要实现ImportBeanDefinitionRegistrar接口
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar{ /** * AnnotationMetadata当前类的注解信息 * BeanDefinitionRegistry:BeanDefinition注册类 * 把所有需要添加到容器中的bean,调用BeanDefinitionRegistry手动注册进来 * */ @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { boolean red = registry.containsBeanDefinition("com.spring.bean.Red"); boolean blue = registry.containsBeanDefinition("com.spring.bean.Blue"); if(red && blue) { //指定Bean定义信息,(bean类型) RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(RainBow.class); //注册一个bean,指定bean名 registry.registerBeanDefinition("rainBow", rootBeanDefinition); } } }
不管用哪种方式将组件注册到IOC容器中,组件对应的bean默认都是单实例的,可以通过@Scope("prototype"),将bean调整为多实例的
@Scope调整作用域
singleton 单实例的 默认值 ioc容器启动会调用方法创建对象到ioc容器中,以后每次获取就是直接从容器中拿
prototype 多实例的 ioc容器启动并不会去调用方法创建对象放在容器中,每次获取的时候才会调用方法创建对象
request 同一次请求创建一个实例
session 同一个session创建一个实例
5.@Conditional
@Conditional({Condition}) 按照一定的条件进行判断,满足条件给容器注册bean
WindowsCondition类:
public class WindowsCondition implements Condition{ @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { Environment environment = context.getEnvironment(); String property = environment.getProperty("os.name"); if(property.contains("Windows")) { return true; } return false; } }
LinuxCondition类:
//判断是否是Linux系统 public class LinuxCondition implements Condition { @Override /** * ConditionContext 判断条件能使用的上下文(环境) * AnnotatedTypeMetadata 注释信息 */ 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(); String property = environment.getProperty("os.name"); if(property.contains("Linux")) { return true; } return false; } }
将LinuxCondition和WindowsCondition注册进IOC容器中,并添加@Conditional标识
@Bean("bill") @Conditional({WindowsCondition.class}) public Person person01() { return new Person("ber",60); } @Bean("linus") @Conditional({LinuxCondition.class}) public Person person02() { return new Person("linux",45); }
ConfigurableEnvironment environment = applicationContext.getEnvironment(); //动态获取环境变量的值:Windows 10 String property = environment.getProperty("os.name"); System.out.println(property);
因为我用的是Windows 10系统,所有,会将person01注册进IOC容器
6.使用Spring提供的FactoryBean(工厂bean),将组件注册进IOC容器
//创建一个Spring定义的FactoryBean public class ColorFactoryBean implements FactoryBean<Color> { //返回一个color对象,这个对象会添加到容器中 @Override public Color getObject() throws Exception { // TODO Auto-generated method stub System.out.println("ColorFactory.....getObject....."); return new Color(); } @Override public Class<?> getObjectType() { // TODO Auto-generated method stub System.out.println("ColorFactory.....getObjectType......"); return Color.class; } //是否是单例 //true,这个bean是单例,在容器中保存一份 //false,多实例,每次获取都会创建一个新的bean @Override public boolean isSingleton() { // TODO Auto-generated method stub return false; } }
将工厂通过@Bean注册进IOC容器
@Bean public ColorFactoryBean colorFactoryBean() { return new ColorFactoryBean(); }
@Test public void testImport() { printBeans(applicationContext); } private void printBeans(AnnotationConfigApplicationContext applicationContext) { String[] strings = applicationContext.getBeanDefinitionNames(); for (String string : strings) { System.out.println(string); } //工厂bean获取的是调用getObject创建的对象 Object bean = applicationContext.getBean("colorFactoryBean"); System.out.println(bean.getClass()); Object bean1 = applicationContext.getBean("&colorFactoryBean"); System.out.println(bean.getClass()); }
原文:https://www.cnblogs.com/TX-wuhe/p/13032287.html