什么是@Bean
@Bean
和@Component
都是将Spring Bean添加到Spring Context 中。
@Bean不能注释在类上,只能作用于方法。
@Bean
注解告诉 Spring 这个方法将会返回一个对象,这个对象要注册为 Spring 应用上下文中的 bean。意思就是,我要获取这个 bean 的时候,Spring 要按照这种方式去获取这个 bean。
@Bean注解参数:
value
:定义bean在IOC容器中的id属性。name
:定义bean在IOC容器中的id属性。autowire
:装配方式- Autowire.NO (默认设置)
- Autowire.BY_NAME
- Autowire.BY_TYPE
initMethod
:指定初始化方法 相当于xml文件中 init-methoddestroyMethod
:指定销毁的方法 相当于xml文件中 destroy-method
@Configuration
@ComponentScan(basePackages = {"springIocTest/pojo"})
public class SpringIocConfig {
@Bean(initMethod = "init", destroyMethod = "destory")
public UserService getUserService(){
return new UserService();
}
}
@Bean一般结合 @Configuration 一起使用,用于配置 spring bean 到 SpringContext 中。
@Component 对比 @Bean
- 共同点
- 两者的目的是一样的,都是注册 bean 到 Spring 容器中。
- 不同点
- 作用域不同
- @Component作用于类,@Bean作用于方法。
- 注册方式不同
@Component
注解表明一个类会作为组件类,并告知 Spring 要为这个类创建 bean。@Bean
注解告诉 Spring 这个方法将会返回一个对象,这个对象要注册为 Spring 应用上下文中的 bean。通常方法体中包含了最终产生bean实例的逻辑。
- 使用方式
@Component
(@Controller
、@Service
、@Repository
)通常是通过类路径扫描来自动侦测以及自动装配到 Spring 容器中。@Bean
一般结合@Configuration
一起使用,也可以配置在类的方法中。
- 作用域不同
默认情况下,@Bean注解的
方法名
默认作为对象的名字,也可以用name
属性定义对象的名字。
使用方式
与配置类@Configuration一起
@Bean
的用途更加灵活,当我们引用第三方库中的类需要装配到 Spring 容器时
,则只能通过@Bean
来实现。
比如,需要引入configTest.AOP.service模块的类ProductService
package configTest;
import configTest.AOP.service.ProductService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration //作为配置类,替代xml配置文件
@ComponentScan(basePackages = {"configTest.pojo"})
public class SpringConfig {
@Bean
public ProductService getProductService() {
return new ProductService();
}
}
程序调用:
package configTest;
import configTest.AOP.service.ProductService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
ProductService product = (ProductService) context.getBean("getProductService");
System.out.println(product);
product.doSomeService();
}
}
运行结果:
通过context.getBean(“getProductService”)获取到ProductService类对象。
单独配置在类的方法中
在类 Stu 中配置 @Bean
package configTest.pojo;
import configTest.AOP.service.ProductService;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
@Component
public class Stu {
public String name;
@Override
public String toString() {
return "Stu{" + "name='" + name + '\'' + '}';
}
@Bean
public ProductService getProductService2() {
return new ProductService();
}
}
程序调用:
package configTest;
import configTest.AOP.service.ProductService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
ProductService product = (ProductService) context.getBean("getProductService");
System.out.println(product);
product.doSomeService();
ProductService product2 = (ProductService) context.getBean("getProductService2");
System.out.println(product2);
product2.doSomeService();
}
}
运行结果:
也可以配置在类方法中。
通过配置返回不同的对象
该案例只能用@Bean
实现。
1、接口IUserDao,实现类UserDaoImpl1、UserDaoImpl2:
IUserDao:
public interface IUserDao {
public void add();
}
UserDaoImpl1:
@Component
public class UserDaoImpl1 implements IUserDao {
@Override
public void add() {
System.out.println("UserDaoImpl1 add");
}
}
UserDaoImpl2:
@Component
public class UserDaoImpl2 implements IUserDao {
@Override
public void add() {
System.out.println("UserDaoImpl2 add");
}
}
2、配置类SpringConfig:
package springIocTest;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@ComponentScan(basePackages = {"springIocTest"})
@PropertySource(value = {"classpath:springIocTest/list.properties"}) //该句不起作用,不知道为什么....,只能通过配置文件加载。
public class SpringConfig {
@Value("${param}")
public String param;
@Bean
public IUserDao getUserDao() {
System.out.println(param);
switch (param) {
case "1":
return new UserDaoImpl1();
case "2":
return new UserDaoImpl2();
}
return null;
}
}
注入属性param,通过配置文件list.properties动态赋值,然后通过@Bean
返回不同类型对象。
配置文件list.properties:
param=1
配置文件applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--引入外部属性文件-->
<context:property-placeholder location="classpath:springIocTest/list.properties"/>
<context:component-scan base-package="springIocTest"/>
</beans>
程序调用:
public class SpringTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("springIocTest/applicationContext.xml");
IUserDao userDao = context.getBean("getUserDao", IUserDao.class);
userDao.add();
}
}
运行结果:
如果list.properties中param=2,则打印 2 UserDaoImpl2 add
。
以上这个例子是无法用@Component以及其具体实现注解(@Controller、@Service、@Repository)来实现的。
总结
@Component
和@Bean
都是用来注册 Bean 并装配到 Spring 容器中,但是@Bean
比@Component
的自定义性更强。可以实现一些@Component
实现不了的自定义加载类。