目录

一、环境初始化

1、环境准备

二、bean的手动注入

1、xml方式注入bean

2、使用@Configuration&@Bean方式注入bean

三、自动扫描注册组件及bean

1、使用xml方式扫描包

2、使用@ComponentScan扫描

3、包扫描的排除

四、组件注册用到的其他注解

1、使用@Scope-设置组件作用域

2、@Lazy-bean懒加载

3、@Conditional-按照条件注册bean

五、使用@Import给容器中快速导入一个组件

1、@Import导入组件

2、使用ImportSelector来导入bean

3、使用ImportBeanDefinitionRegistrar来导入bean

六、使用FactoryBean创建bean

1、使用FactoryBean创建bean

七、bean组件注册小结


友情提示:此系列文档不适宜springboot零基础的同学~

一、环境初始化

1、环境准备

(1)新建maven项目。

(2)pom导入spring-bean有关的包,以及junit测试

<!--引入spring-bean有关的包-->
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>4.3.12.RELEASE</version>
</dependency>
<!--junit测试-->
<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope>
</dependency>

(3)环境包如下

二、bean的手动注入

1、xml方式注入bean

(1)定义Person类

package com.xiang.spring.bean;public class Person {private String name;private Integer age;……get set toString……
}

(2)在resources目录下创建beans.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!--使用xml配置bean--><bean id="person" class="com.xiang.spring.bean.Person"><property name="age" value="18"></property><property name="name" value="lisi"></property></bean>
</beans>

(3)创建main方法来获取ioc中的bean

package com.xiang.spring;import com.xiang.spring.bean.Person;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class MainTest {public static void main(String[] args) {// 使用xml配置文件获取容器中的beanApplicationContext applicationContextXml = new ClassPathXmlApplicationContext("beans.xml");Person xmlPerson = (Person) applicationContextXml.getBean("person");System.out.println(xmlPerson);}
}

2、使用@Configuration&@Bean方式注入bean

(1)定义Person类

同上

(2)创建配置类

package com.xiang.spring.config;import com.xiang.spring.bean.Person;
import org.springframework.context.annotation.Bean;// 告诉spring这是一个配置类
@Configuration
public class MainConfig {/*** 给容器中注册一个bean,类型为返回值的类型,默认是用方法名作为id名称* 使用@Bean("person") 可以给bean指定名称,而不用方法名*///@Bean@Bean("person")public Person person01() {return new Person("zhangsan", 20);}}

(3)创建main方法来获取ioc中的bean

package com.xiang.spring;import com.xiang.spring.bean.Person;
import com.xiang.spring.config.MainConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class MainTest {public static void main(String[] args) {// 使用xml配置文件获取容器中的beanApplicationContext applicationContextXml = new ClassPathXmlApplicationContext("beans.xml");Person xmlPerson = (Person) applicationContextXml.getBean("person");System.out.println(xmlPerson);System.out.println("------------------------");// 创建IOC容器,加载配置类,获取到容器中的PersonApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);// 多种方式获取容器中的beanPerson bean = applicationContext.getBean(Person.class);Person bean2 = applicationContext.getBean("person", Person.class);System.out.println(bean);System.out.println(bean2);// 获取指定class类型的bean的名字(默认为bean的方法名)String[] beanNamesForType = applicationContext.getBeanNamesForType(Person.class);for (String s : beanNamesForType) {System.out.println(s);}}
}// 运行结果
Person{name='lisi', age=18}
------------------------
Person{name='zhangsan', age=20}
Person{name='zhangsan', age=20}
person

三、自动扫描注册组件及bean

1、使用xml方式扫描包

(1)在beans.xml添加以下内容

<!--包扫描,只要标注了@Controller、@Service、@Repository、@Component的bean都会创建到容器中-->
<!--use-default-filters禁用默认规则,才可以继续设置扫描过滤规则-->
<context:component-scan base-package="com.xiang.spring" use-default-filters="false"></context:component-scan>

2、使用@ComponentScan扫描

(1)定义Controller、Service、Dao类

package com.xiang.spring.controller;
import org.springframework.stereotype.Controller;
@Controller
public class BookController {
}package com.xiang.spring.service;
import org.springframework.stereotype.Service;
@Service
public class BookService {
}package com.xiang.spring.dao;
import org.springframework.stereotype.Repository;
@Repository
public class BookDao {
}

(2)设置配置类

package com.xiang.spring.config;import com.xiang.spring.bean.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;// 告诉spring这是一个配置类
@Configuration
@ComponentScan(value = "com.xiang.spring")
public class MainConfig {/*** 给容器中注册一个bean,类型为返回值的类型,默认是用方法名作为id名称* 使用@Bean("person") 可以给bean指定名称,而不用方法名*///@Bean@Bean("person")public Person person01() {return new Person("zhangsan", 20);}
}

(3)写测试类获取ioc容器中所有注册的bean

package com.xiang.spring.test;import com.xiang.spring.config.MainConfig;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class IOCTest {@Testpublic void test01(){// 获取IOC容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);// 获取容器中的所有bean名称String[] definitionNames = applicationContext.getBeanDefinitionNames();for (String definitionName : definitionNames) {System.out.println(definitionName);}}
}// 运行结果
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
bookController
bookDao
bookService
person

3、包扫描的排除

(1)excludeFilters排除需要扫描的组件

修改配置类

package com.xiang.spring.config;import com.xiang.spring.bean.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;// 告诉spring这是一个配置类
@Configuration
/**
* 包扫描,只要标注了@Controller、@Service、@Repository、@Component的bean都会创建到容器中
* @ComponentScan :value:指定要扫描的包;
*                   excludeFilters = Filter[]: 指定扫描的时候按照什么规则排除哪些组件
*                   includeFilters = Filter[]: 指定扫描的时候只需要包含哪些组件,还需要加useDefaultFilters = false
*      jdk8以上可以写多个@ComponentScan,非jdk8以上也可以用@ComponentScans = {@ComponentScan},用来指定多个扫描的包
*/
@ComponentScan(value = "com.xiang.spring", excludeFilters = {@Filter(type = FilterType.ANNOTATION, classes = {Controller.class, Service.class}) // 根据注解排除,排除Controller、Service
})
public class MainConfig {/*** 给容器中注册一个bean,类型为返回值的类型,默认是用方法名作为id名称* 使用@Bean("person") 可以给bean指定名称,而不用方法名*///@Bean@Bean("person")public Person person01() {return new Person("zhangsan", 20);}
}// 运行结果
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
bookDao
person

(2)includeFilters只需要包含哪些组件

修改配置类

package com.xiang.spring.config;import com.xiang.spring.bean.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;// 告诉spring这是一个配置类
@Configuration
/**
* 包扫描,只要标注了@Controller、@Service、@Repository、@Component的bean都会创建到容器中
* @ComponentScan :value:指定要扫描的包;
*                   excludeFilters = Filter[]: 指定扫描的时候按照什么规则排除哪些组件
*                   includeFilters = Filter[]: 指定扫描的时候只需要包含哪些组件,还需要加useDefaultFilters = false
*      jdk8以上可以写多个@ComponentScan,非jdk8以上也可以用@ComponentScans = {@ComponentScan},用来指定多个扫描的包
*/
@ComponentScan(value = "com.xiang.spring", includeFilters = {@Filter(type = FilterType.ANNOTATION, classes = {Controller.class, Service.class}) // 需要包含哪些组件:Controller、Service
}, useDefaultFilters = false)
public class MainConfig {/*** 给容器中注册一个bean,类型为返回值的类型,默认是用方法名作为id名称* 使用@Bean("person") 可以给bean指定名称,而不用方法名*///@Bean@Bean("person")public Person person01() {return new Person("zhangsan", 20);}
}// 运行结果
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
bookController
bookService
person

(3)包扫描排除的枚举类型详解

public enum FilterType {ANNOTATION, // 注解类型ASSIGNABLE_TYPE, // 按照指定的类型ASPECTJ, // 按照Aspectj的表达式,基本不会用到REGEX, // 按照正则表达式CUSTOM; // 自定义规则private FilterType() {}
}

(4)按照指定的类型排除

在配置类中配置:

@Filter(type = FilterType.ASSIGNABLE_TYPE, classes = BookService.class) // 排除规则,只有BookService会排除

(5)自定义排除规则

① 写过滤规则类

package com.xiang.spring.config;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;import java.io.IOException;/**
* 自定义包扫描排除规则类
*/
public class MyTypeFilter implements TypeFilter {/*** MetadataReader :读取到的当前正在扫描的类的信息* MetadataReaderFactory:可以获取到其他任何类的信息*/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);if(className.contains("er")){return true;}// 返回true为匹配成功;返回false为匹配结束return false;}
}

② 配置类中设置自定义过滤规则

// 告诉spring这是一个配置类
@Configuration
@ComponentScan(value = "com.xiang.spring", includeFilters = {@Filter(type = FilterType.CUSTOM, classes = MyTypeFilter.class) // 自定义过滤规则
}, useDefaultFilters = false)
public class MainConfig {

③ 执行test类查看结果

package com.xiang.spring.test;import com.xiang.spring.config.MainConfig;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class IOCTest {@Testpublic void test01(){// 获取IOC容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);// 获取容器中的所有bean名称String[] definitionNames = applicationContext.getBeanDefinitionNames();for (String definitionName : definitionNames) {System.out.println(definitionName);}}
}// 打印结果
----->com.xiang.spring.test.IOCTest
----->com.xiang.spring.bean.Person
----->com.xiang.spring.config.MyTypeFilter
----->com.xiang.spring.controller.BookController
----->com.xiang.spring.dao.BookDao
----->com.xiang.spring.MainTest
----->com.xiang.spring.service.BookService
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
person
myTypeFilter
bookController
bookService

四、组件注册用到的其他注解

1、使用@Scope-设置组件作用域

(1)定义配置类

package com.xiang.spring.config;import com.xiang.spring.bean.Person;
import org.springframework.context.annotation.*;
import org.springframework.context.annotation.ComponentScan.Filter;@Configuration
public class MainConfig2 {/***  默认是单例的,配置方式有四种(取自@Scope的value的注释)* @see ConfigurableBeanFactory#SCOPE_PROTOTYPE* @see ConfigurableBeanFactory#SCOPE_SINGLETON* @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST* @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION** 解析:*  prototype:多实例的:ioc容器启动不会调用方法创建对象,每次获取的时候才会调用方法创建对象,每次获取都会调用方法获取对象。*  singleton:单实例的(默认值):ioc容器启动,会调用方法创建对象放到ioc容器中,以后每次取就是直接从容器中拿。*  request:同一次请求创建一个实例(web环境可用,但也不常用)*  session:同一个session创建一个实例(web环境可用,但也不常用)*/@Scope("prototype")@Bean("person2")public Person person() {System.out.println("给容器中添加Person……");return new Person("zhangsan", 22);}
}

(2)编写测试方法

@Test
public void test02(){// 获取IOC容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);// 默认是单实例Object obj1 = applicationContext.getBean("person2");Object obj2 = applicationContext.getBean("person2");System.out.println(obj1 == obj2);
}// 运行结果
给容器中添加Person……
给容器中添加Person……
false

2、@Lazy-bean懒加载

(1)在bean加上@Lazy注解

/**
* 单实例bean:默认在容器启动的时候创建对象。
* 懒加载:容器启动不创建对象,第一次使用(获取)bean时才创建对象,并初始化。
*
*/
@Lazy
@Bean("person2")
public Person person() {System.out.println("给容器中添加Person……");return new Person("zhangsan", 22);
}

(2)编写测试方法

@Test
public void test02(){// 获取IOC容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);// 默认是单实例System.out.println("--------------");Object obj1 = applicationContext.getBean("person2");
}// 输出结果
--------------
给容器中添加Person……

3、@Conditional-按照条件注册bean

(1)编写两个Condition

package com.xiang.spring.condition;
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系统
public class WindowsCondition implements Condition {public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {// 能获取到环境信息Environment environment = context.getEnvironment();// 获取操作系统String osName = environment.getProperty("os.name");if(osName.contains("Windows")){return true;}return false;}
}package com.xiang.spring.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系统
public class LinuxCondition implements Condition {/*** ConditionContext:判断条件能使用的上下文环境* AnnotatedTypeMetadata:当前标记了@Conditional的注释信息*/public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {// 能获取到ioc使用的beanFactory工厂ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();// 能获取到类加载器ClassLoader classLoader = context.getClassLoader();// 能获取到环境信息Environment environment = context.getEnvironment();// 获取到bean定义的注册类BeanDefinitionRegistry registry = context.getRegistry();// 可以判断容器中是否包含bean的定义,也可以给容器中注册beanregistry.containsBeanDefinition("person");// 获取操作系统String osName = environment.getProperty("os.name");if(osName.contains("linux")){return true;}return false;}
}

(2)配置类中添加bean

/**
* @Conditional({}):按照一定的条件进行判断,满足条件给容器中注册bean
* 既可以放在方法上,也可以放在类上进行统一设置
*/
@Conditional({LinuxCondition.class})
@Bean
public Person linux() {return new Person("linux", 60);
}
@Conditional({WindowsCondition.class})
@Bean
public Person windows() {return new Person("windows", 50);
}

(3)测试方法测试一下

@Test
public void test03(){// 获取IOC容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);ConfigurableEnvironment environment = applicationContext.getEnvironment();System.out.println("当前运行环境" + environment.getProperty("os.name"));Map<String, Person> beansOfType = applicationContext.getBeansOfType(Person.class);System.out.println(beansOfType);
}// 运行结果
当前运行环境Windows 10
{windows=Person{name='windows', age=50}}

五、使用@Import给容器中快速导入一个组件

1、@Import导入组件

(1)新增类

public class Color {
}public class Red {
}

(2)在配置类上添加注解

@Configuration
// 导入组件,id默认是组件的全类名
@Import({Color.class, Red.class})
public class MainConfig2 {

(3)测试方法测试一下

@Test
public void test04(){// 获取IOC容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);String[] definitionNames = applicationContext.getBeanDefinitionNames();for (String name : definitionNames) {System.out.println(name);}
}// 运行结果
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig2
com.xiang.spring.bean.Color
com.xiang.spring.bean.Red

2、使用ImportSelector来导入bean

(1)定义bean类

public class Blue {
}public class Yellow {
}

(2)编写selector

package com.xiang.spring.condition;import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;/**
* 自定义返回逻辑需要导入的组件
*/
public class MyImportSelector implements ImportSelector {/*** 返回值就是导入到容器中的组件全类名* AnnotationMetadata:当前标注@Import的类的所有注解信息*/public String[] selectImports(AnnotationMetadata importingClassMetadata) {// 方法不要返回null值return new String[]{"com.xiang.spring.bean.Blue", "com.xiang.spring.bean.Yellow"};}
}

(3)配置类添加

@Configuration
// 导入组件,id默认是组件的全类名
@Import({Color.class, Red.class, MyImportSelector.class})
public class MainConfig2 {

(4)运行一下看结果

@Test
public void test04(){// 获取IOC容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);String[] definitionNames = applicationContext.getBeanDefinitionNames();for (String name : definitionNames) {System.out.println(name);}
}//执行结果
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig2
com.xiang.spring.bean.Color
com.xiang.spring.bean.Red
com.xiang.spring.bean.Blue
com.xiang.spring.bean.Yellow

3、使用ImportBeanDefinitionRegistrar来导入bean

(1)编写bean类

public class RainBow {
}

(2)注册类

package com.xiang.spring.condition;import com.xiang.spring.bean.RainBow;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {/*** AnnotationMetadata:当前类注解信息* BeanDefinitionRegistry:BeanDefinition注册类*  把所有需要添加到容器中的bean,调用BeanDefinitionRegistry.registerBeanDefinition手工注册*/public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {boolean red = registry.containsBeanDefinition("com.xiang.spring.bean.Red");boolean blue = registry.containsBeanDefinition("com.xiang.spring.bean.Blue");if(red && blue) {// 指定bean的定义信息RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(RainBow.class);// 指定bean名,注册一个beanregistry.registerBeanDefinition("rainBow", rootBeanDefinition);}}
}

(3)配置类

@Configuration
@Import({Color.class, Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class MainConfig2 {

(4)编写测试方法看结果

@Test
public void test04(){// 获取IOC容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);String[] definitionNames = applicationContext.getBeanDefinitionNames();for (String name : definitionNames) {System.out.println(name);}
}// 运行结果
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig2
com.xiang.spring.bean.Color
com.xiang.spring.bean.Red
com.xiang.spring.bean.Blue
com.xiang.spring.bean.Yellow
rainBow

六、使用FactoryBean创建bean

1、使用FactoryBean创建bean

(1)定义FactoryBean

package com.xiang.spring.bean;import org.springframework.beans.factory.FactoryBean;/**
* 创建一个spring定义的工厂bean
*/
public class ColorFactoryBean implements FactoryBean<Color> {/*** 返回一个Color对象,这个对象会添加到容器中* 假如说不是单例,每次获取bean都会调用getObject方法*/public Color getObject() throws Exception {return new Color();}public Class<?> getObjectType() {return Color.class;}/*** 控制是否是单例的* true:单例,在容器中保存一份* false:不是单例,每次获取都会创建新实例*/public boolean isSingleton() {return false;}
}

(2)配置类添加FactoryBean

@Bean
public ColorFactoryBean colorFactoryBean() {return new ColorFactoryBean();
}

(3)测试类查看输出结果

@Test
public void test04(){// 获取IOC容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);String[] definitionNames = applicationContext.getBeanDefinitionNames();for (String name : definitionNames) {System.out.println(name);}// 默认获取到的是工厂bean调用getObject创建的对象Object colorFactoryBean = applicationContext.getBean("colorFactoryBean");System.out.println("colorFactoryBean的类型:" + colorFactoryBean.getClass());// 要获取工厂bean本身,我们需要给id前面加一个&符号:&colorFactoryBeanObject colorFactoryBean2 = applicationContext.getBean("&colorFactoryBean");System.out.println("colorFactoryBean2的类型:" + colorFactoryBean2.getClass());
}// 输出结果
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig2
colorFactoryBean
colorFactoryBean的类型:class com.xiang.spring.bean.Color
colorFactoryBean2的类型:class com.xiang.spring.bean.ColorFactoryBean

七、bean组件注册小结

给容器中注册组件

(1)、包扫描+组件标注注解(@Controller/@Service/@Repository/@Component)

(2)、@Bean[导入第三方包里面的组件]

(3)、@Import[快速给容器中导入一个组件]

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

② ImportSelector:返回需要导入的组件的全类名数组

③ ImportBeanDefinitionRegistrar:手动注册bean到容器中

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

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

② 要获取工厂bean本身,我们需要给id前面加一个&符号:&colorFactoryBean

spring系列-注解驱动原理及源码-bean组件注册相关推荐

  1. spring系列-注解驱动原理及源码-bean生命周期

    目录 一.Bean的初始化和销毁 1.@Bean指定初始化和销毁方法 2.通过实现InitializingBean和Disposabean来初始化和销毁bean 3.使用JSR250定义的@PostC ...

  2. spring系列-注解驱动原理及源码-声明式事务使用及原理解析

    目录 一.环境准备 1.JdbcTemplate使用实例 2.事务添加 二.声明式事务源码分析 1.原理(与AOP非常相似) 一.环境准备 1.JdbcTemplate使用实例 (1)pom文件添加依 ...

  3. spring系列-注解驱动原理及源码-自动装配

    目录 一.spring规范的bean自动注入 1.使用@Autowired自动注入 2.使用@Qualifier指定需要装配的组件 3.使用@Autowired装配null对象 4.使用@Primar ...

  4. spring系列-注解驱动原理及源码-AOP使用及源码解析

    目录 一.用注解方式开启AOP 1.实例 2.AOP简单小结 二.AOP原理 1.@EnableAspectJAutoProxy溯源 2.AnnotationAwareAspectJAutoProxy ...

  5. spring系列-注解驱动原理及源码-spring容器创建流程

    目录 一.spring容器的refresh()[创建刷新] 二.BeanFactory 的创建及预准备工作 1.prepareRefresh()刷新前预处理工作. 2.obtainFreshBeanF ...

  6. spring系列-注解驱动原理及源码-属性赋值

    目录 一.bean属性赋值 1.bean属性使用@Value赋值 2.bean属性通过配置文件赋值 一.bean属性赋值 1.bean属性使用@Value赋值 (1)编写bean类 package c ...

  7. 手撸Spring系列12:MyBatis(源码篇)

    说在前头: 笔者本人为大三在读学生,书写文章的目的是为了对自己掌握的知识和技术进行一定的记录,同时乐于与大家一起分享,因本人资历尚浅,发布的文章难免存在一些错漏之处,还请阅读此文章的大牛们见谅与斧正. ...

  8. Dubbo源码分析-Spring与Dubbo整合原理与源码分析(二)

    Spring与Dubbo整合的整体流程(基于apache-dubbo-2.7.15) 因为dubbo有较多的兼容以前的代码比如@DubboReference 以前就有两个版本@Reference 和@ ...

  9. spring依赖注入底层原理与源码分析

    Spring中有几种依赖注入方式? 1.手动注入-set方法注入和构造器注入 2.自动注入-@Autowired注解和xml注入 autowrire参数: no 默认不开启 byName 根据被注入属 ...

最新文章

  1. VMWare虚拟机与主机共享文件夹(如何安装VMWare tools)windows与windows共享
  2. 使用Dropwizard度量标准监视和测量无功应用
  3. 关于我曾经做过的一个商业社区的ui框架
  4. 在一个机器上创建多个独立Firefox运行环境
  5. 关键路径 - 数据结构和算法67
  6. 后疫情时代,用户到访识别已成为商业地产数字化升级“近义词”
  7. 抖音订单捉取-php
  8. 好程序员web前端分享如何构建单页Web应用
  9. Java--------面向对象
  10. 路由器登陆192.168.1.1打开后出现移动登陆页面
  11. 如何使用SQL对数据进行分析和可视化
  12. 深入浅出学K8s - 详解K8s的网络模型
  13. 【信息安全】EDR、HIDS、NDR、MDR、XDR 区别与联系
  14. 达人评测 r33200g和i510400f选哪个好
  15. 《区块链技术与应用》读书笔记
  16. DDIM代码详细解读(4):分类器classifier的网络设计、训练、推理
  17. 5.2 BGP水平分割
  18. 微信小程序学习-组件Map-地图初始定位
  19. Mission Planner初学者安装调试教程指南(APM或PIX飞控)1——下载与版本
  20. 【Elasticsearch入门】Elasticsearch集群管理

热门文章

  1. 如何解决error: failed to push some refs to ‘xxx(远程库)‘
  2. java中调用api的方式(postJsonHTTP)
  3. JUC系列(二)回顾Synchronized关键字
  4. opencv 通过标定摄像头测量物体大小_视觉激光雷达信息融合与联合标定
  5. python读取图片属性_[Python图像处理]三.获取图像属性及通道处理
  6. python 网络设备管理软件_一个查看网络设备信息Python小程序
  7. Ubuntu ORTP 编译及安装
  8. 什么叫pmt测试分析_直读分析光谱仪核心配件
  9. java对灰度值进行线性变换,灰度变换
  10. 32位选择进位加法器_32位加减法器设计