@Configuration
代表这个类是一个配置类,可理解为用spring的时候xml里面的<beans>标签
@Bean
用来定义一个bean,可以指定初始、销毁方法,及bean范围等,可理解为用spring的时候xml里面的<bean>标签
@ComponentScan
用来扫描指定包下面的注解类,相当于<context:component-scan base-package="com.xxx.xxx" />,普通的spring项目好多注解都需要扫包才有用
@Scope 调整作用域,来指定bean生成的对象是什么类型的。prototype:多实例的。singleton:单实例的(默认值)。request:同一次请求创建一个实例。session:同一个session创建一个实例。
@Lazy
懒加载,只有在创建单实例bean时才会生效,默认在容器启动的时候创建对象,添加了此注解后,容器启动不创建对象,而是在第一次使用(获取)Bean创建对象,并初始化。
@Import
用来导入其他的@Configuration配置类。
@ImportResource
用来导入xml配置文件,比如某些配置一定要xml配置。
@Component
加到类路径自动扫描 。@Controller:一个web的控制层,在Spring MVC中使用 。@Repository:数据管理/存储,企业级应用使用(Dao, DDD) 。@Service 提供一个商业逻辑: 一个无状态的切面。
Spring帮助我们管理Bean分为两个部分,一个是注册Bean,一个装配Bean。 完成这两个动作有三种方式,一种是使用自动配置的方式、一种是使用JavaConfig的方式,一种就是使用XML配置的方式。
在自动配置的方式中,使用@Component去告诉Spring,我是一个bean,你要来管理我,然后使用@AutoWired注解去装配Bean(所谓装配,就是管理对象直接的协作关系)。
在JavaConfig中,@Configuration其实就是告诉spring,spring容器要怎么配置(怎么去注册bean,怎么去处理bean之间的关系(装配))。@Bean的意思就是,我要获取这个bean的时候,你spring要按照这种方式去帮我获取到这个bean。
在使用xml的方式中,<bean>标签就是告诉spring怎么获取这个bean,各种<ref>就是手动的配置bean之间的关系。
用@Bean注解的方法:会实例化、配置并初始化一个新的对象,这个对象会由spring IoC 容器管理。
@Configuration public class AppConfig {
@Bean public MyService myService() { return new MyServiceImpl(); }
}
相当于在 XML 文件中配置
<beans> <bean id="myService" class="com.acme.services.MyServiceImpl"/> </beans>
生成对象的名字:默认情况下用@Bean注解的方法名作为对象的名字。但是可以用 name属性定义对象的名字
@Configuration public class AppConfig { @Bean(name = "myFoo") public Foo foo() { return new Foo(); } }
而且还可以使用name为对象起多个名字。
@Configuration public class AppConfig { @Bean(name = { "dataSource", "subsystemA-dataSource", "subsystemB-dataSource" }) public DataSource dataSource() { // instantiate, configure and return DataSource bean... } }
在 @Component 注解的类中不能定义 类内依赖的@Bean注解的方法。@Configuration可以。 @Configuration public class AppConfig {
@Bean public Foo foo() { return new Foo(bar()); }
@Bean public Bar bar() { return new Bar(); }
}
@Configuration public class MyTestConfig {
@Bean public Driver driver(){ Driver driver = new Driver(); driver.setId(1); driver.setName("driver"); driver.setCar(car()); return driver; }
@Bean public Car car(){ Car car = new Car(); car.setId(1); car.setName("car"); return car; } }
测试代码如下
@RunWith(SpringRunner.class) @SpringBootTest public class TestApplicationTests {
@Autowired private Car car;
@Autowired private Driver driver;
@Test public void contextLoads() { boolean result = driver.getCar() == car; System.out.println(result ? "同一个car" : "不同的car"); }
}
打印结果如下: 同一个car
替换为Component后的打印结果: 不同的car
从上面的结果可以发现使用Configuration时在driver和spring容器之中的是同一个对象,而使用Component时是不同的对象。 虽然Component注解也会当做配置类,但是并不会为其生成CGLIB代理Class,所以在生成Driver对象时和生成Car对象时调用car()方法执行了两次new操作,所以是不同的对象。当时Configuration注解时,生成当前对象的子类Class,并对方法拦截,第二次调用car()方法时直接从BeanFactory之中获取对象,所以得到的是同一个对象。