持续学习&持续更新中…
守破离
【Java从零到架构师第③季】【20】Spring-@Configuration_@Bean
一、@Configuration、@Bean
如果bean对象的创建过程比较复杂,就可以使用@Bean代替@Component
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
@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容器中,必须被容器所管理。
例子:
@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容器中,必须被容器所管理。
例子:
这里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
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方法的注入—其他类型
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到架构师③进阶互联网架构师.
本文完,感谢您的关注支持!