目录

​一、环境初始化​

​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)环境包如下

spring系列-注解驱动原理及源码-bean组件注册_spring


二、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配置文件获取容器中的bean
ApplicationContext 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配置文件获取容器中的bean
ApplicationContext applicationContextXml = new ClassPathXmlApplicationContext("beans.xml");
Person xmlPerson = (Person) applicationContextXml.getBean("person");
System.out.println(xmlPerson);
System.out.println("------------------------");
// 创建IOC容器,加载配置类,获取到容器中的Person
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
// 多种方式获取容器中的bean
Person 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 {

@Test
public 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 {

@Test
public 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的定义,也可以给容器中注册bean
registry.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名,注册一个bean
registry.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前面加一个&符号:&colorFactoryBean
Object 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