目录
1、环境准备
2、使用@Configuration&@Bean方式注入bean
3、使用ImportBeanDefinitionRegistrar来导入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配置文件获取容器中的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