【Java从零到架构师第③季】【20】Spring-@Configuration_@Bean


持续学习&持续更新中…

守破离


【Java从零到架构师第③季】【20】Spring-@Configuration_@Bean

一、@Configuration、@Bean

如果bean对象的创建过程比较复杂,就可以使用@Bean代替@Component

【Java从零到架构师第③季】【20】Spring-@Configuration_@Bean

1、基本使用

applicationContext.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 https://www.springframework.org/schema/context/spring-context.xsd">

	<!-- 没有配置:
		<bean id="dog" class="programmer.lp.domain.Dog"/>
	-->

    <context:component-scan base-package="programmer.lp"/>

</beans>

Dog:

// 没有配置@Component
public class Dog {
    private String name;
    private String nickName;

    public Dog() {
    }
	
	// ...
}

BeanConfiguration:

@Configuration
public class BeanConfiguration {

    @Bean
    public Dog dog() {
        return new Dog();
    }

}

测试:

    @Test
    public void testPerson() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        Dog dog = ctx.getBean("dog", Dog.class);
        System.out.println(dog);
    }

2、name、value

【Java从零到架构师第③季】【20】Spring-@Configuration_@Bean

@Configuration
public class BeanConfiguration {

    @Bean("babyDog")
    public Dog dog() {
        return new Dog();
    }

}
    @Test
    public void testPerson() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        Dog dog = ctx.getBean("babyDog", Dog.class);
        System.out.println(dog);
    }

二、@Bean方法的注入—bean属性有@Autowired

核心思想:要想使用@Autowired自动注入某个对象,就必须确保这个对象存在于IoC容器中,必须被容器所管理

【Java从零到架构师第③季】【20】Spring-@Configuration_@Bean

例子

@Component
public class Food {
	// ...
}

这里Human给food属性使用了@Autowired

public class Human {
    private Food food;
    @Autowired
    public void setFood(Food food) {
        this.food = food;
    }
}
@Configuration
public class BeanConfiguration {
    @Bean
    public Human human() {
        return new Human();
    }
}
    @Test
    public void test() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        Human human = ctx.getBean("human", Human.class);
        System.out.println(human);
    }

注意:要想让bean被IoC容器管理,常见的有如下几种方式:

方式一:

@Component
public class Food {
    // ...
}

方式二:

public class Food {
    // ...
}
<bean id="food" class="programmer.lp.domain.Food">
    <!-- ...属性... -->
</bean>

方式三:

public class Food {
    // ...
}
@Configuration
public class BeanConfiguration {
    @Bean
    public Food food() {
        return new Food();
    }
}

方式四:

public class Food {
    // ...
}
public class FoodFactoryBean implements FactoryBean<Food> {
    @Override
    public Food getObject() throws Exception {
        // 假设Food对象创建过程很复杂
        return new Food();
    }

    @Override
    public Class<?> getObjectType() {
        return Food.class;
    }
}
@Configuration
public class BeanConfiguration {
	
	// ...
    @Bean
    public FoodFactoryBean food() {
        return new FoodFactoryBean();
    }

}

方式五:

public class Food {
    // ...
}
@Component("food")
public class FoodFactoryBean implements FactoryBean<Food> {
    @Override
    public Food getObject() throws Exception {
        // 假设Food对象创建过程很复杂
        return new Food();
    }

    @Override
    public Class<?> getObjectType() {
        return Food.class;
    }
}

方式X:只要能被IoC容器管理就行。

三、@Bean方法的注入—bean属性没有@Autowired

核心思想:要想使用@Autowired自动注入某个对象,就必须确保这个对象存在于IoC容器中,必须被容器所管理

【Java从零到架构师第③季】【20】Spring-@Configuration_@Bean

例子

这里Human没有给food属性使用@Autowired

public class Human {
    private Food food;
    public void setFood(Food food) {
        this.food = food;
    }
}

实现一:

@Configuration
public class BeanConfiguration {

	// 前提:Food必须要存在于IoC容器中,见上面几种方式
	// 使用@Bean修饰的方法,Spring会使用@Autowired自动注入方法参数
    @Bean
    public Human human(Food food) {
        Human human = new Human();
        human.setFood(food);
        return human;
    }

}

实现二:

@Configuration
public class BeanConfiguration {
    @Bean
    public Food food() {
        return new Food();
    }

    @Bean
    public Human human() {
        Human human = new Human();
        // 这儿看起来直接调用了food()方法,但是实际上并不会直接调用
        // Spring在底层使用了动态代理技术,直接调用时,会调用代理对象的代理方法
        // 最终实现肯定还是ctx.getBean()
        human.setFood(food()); 
        return human;
    }
}

四、@Bean方法的注入—FactoryBean

【Java从零到架构师第③季】【20】Spring-@Configuration_@Bean

DogFactoryBean:

public class DogFactoryBean implements FactoryBean<Dog> {
    @Override
    public Dog getObject() throws Exception {
        // 假设Dog对象创建过程很复杂
        return new Dog();
    }

    @Override
    public Class<?> getObjectType() {
        return Dog.class;
    }
}

使用方式一:

@Configuration
public class BeanConfiguration {
	// ...
    @Bean
    public DogFactoryBean dog() {
        return new DogFactoryBean();
    }
}

使用方式二:

@Component("dog")
public class DogFactoryBean implements FactoryBean<Dog> {
    @Override
    public Dog getObject() throws Exception {
        // 假设Dog对象创建过程很复杂
        return new Dog();
    }

    @Override
    public Class<?> getObjectType() {
        return Dog.class;
    }
}

使用方式三:

	<bean id="dog" class="programmer.lp.factorybean.DogFactoryBean"/>

测试:

	@Test
	public void dogTest() {
	    ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
	    System.out.println(ctx.getBean("dog"));
	    System.out.println(ctx.getBean("&dog"));
	}

五、@Bean方法的注入—其他类型

【Java从零到架构师第③季】【20】Spring-@Configuration_@Bean

public class Dog {
    private String name;
    private String nickName;
    // ...
}
@Configuration
@PropertySource("dog.properties")
public class BeanConfiguration {
    private String dogName;
    private String dogNickName;

    @Value("${name}")
    public void setDogName(String dogName) {
        this.dogName = dogName;
    }
    @Value("${nickName}")
    public void setDogNickName(String dogNickName) {
        this.dogNickName = dogNickName;
    }

    @Bean
    public Dog dog() {
        Dog dog = new Dog();
        dog.setName(dogName);
        dog.setNickName(dogNickName);
        return dog;
    }
}

注意和一些细节

  • 要想使用@Autowired自动注入某个对象,就必须确保这个对象存在于IoC容器中,必须被容器所管理

  • Spring是一个容器框架

参考

小码哥-李明杰: Java从0到架构师③进阶互联网架构师.


本文完,感谢您的关注支持!


上一篇:「初识」SpringBoot 属性注入的方式


下一篇:Spring @bean 和 @component 注解有什么区别?