我们先快速说下,几个注解的作用:
@Configuration:告诉spring容器,这是一个配置类,类似xml中的<beans>注解
@Bean:跟@Configuration配合使用,标注在方法上,实例化一个bean,默认以方法名称做bean的id,可以指定别名,初始化方法和销毁方法
@Scope:跟@bean配置使用,标注在方法上,调整作用域,指定bean创建的定义
prototype:多实例的:ioc容器启动并不会去调用方法创建对象放在容器中。每次获取的时候才会调用方法创建对象;
singleton:单实例的(默认值):ioc容器启动会调用方法创建对象放到ioc容器中,以后每次获取就是直接从容器 (map.get())中拿
request:同一次请求创建一个实例(web环境下)
session:同一个session创建一个实例(web环境下)
@Lazy:懒加载,配合@Bean使用,单实例bean:默认在容器启动的时候创建对象;容器启动不创建对象。第一次使用(获 取)Bean创建对象,并初始化;
创建一个工程,引入spring的基础包
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.12.RELEASE</version>
</dependency>
创建一个基础的测试对象
package com.badger.spring.bean;
public class Person {
private String name;
private int age;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
首先,在spring 4.x之前的版本中,我们对于bean的注入方式是通过xml文件的形式配置的,如下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" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
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-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
<bean id="person" class="com.badger.spring.bean.Person">
<property name="age" value="18"></property>
<property name="name" value="xiali"></property>
</bean>
</beans>
spring4.x之后,支持了注解式编程,如下配置
package com.badger.spring.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.badger.spring.bean.Person;
@Configuration
public class MyConfig {
// 给容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id
@Bean
public Person person() {
return new Person("xiaoli", 20);
}
}
首先,@Configuration注解,类似于之前xml文件里的<beans>的标签,告诉spring,这是一个配置类;
@Bean 相当于xml文件中的<bean>,我们细看@Bean注解里的内容;
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Bean {
@AliasFor("name")
String[] value() default {};
@AliasFor("value")
String[] name() default {};
Autowire autowire() default Autowire.NO;
String initMethod() default "";
String destroyMethod() default AbstractBeanDefinition.INFER_METHOD;
}
value,name属性:默认情况下,注入的bean实例,是以方法名称,作为bean的注入id,也可以通过@Bean注解里的name或者value指定名称,另外name和value都是数组,表示可以取多个名字;
autowire属性:这个是指自动装配时候的引用,xml中,也有这个属性,默认就是NO,这个是spring的自动装配里的规则,我们以后再讲
<bean id="test" class="com.badger.test" autowire="byType"/>
Autowire的枚举中,属性有3个
1、 No:即不启用自动装配。Autowire默认的值。
2、 byName:通过属性的名字的方式查找JavaBean依赖的对象并为其注入。
3、 byType:通过属性的类型查找JavaBean依赖的对象并为其注入。
initMethod,destroyMethod 属性,是指指定bean的初始化方法,以及销毁方法 如下,我们在需要被注入的Person对象中,加init(),detory()方法,那么实体bean就变成如下
package com.badger.spring.bean;
public class Person {
private String name;
private int age;
public Person() {
super();
System.out.println("创建对象");
}
public Person(String name, int age) {
this();
this.name = name;
this.age = age;
}
public void init() {
System.out.println("init ……");
}
public void detory() {
System.out.println("detory ……");
}
//免去get set
}
bane注入的时候,指定初始化方法和销毁方法就好了
@Bean(initMethod = "init", destroyMethod = "detory")
public Person person01() {
return new Person("xiaoli", 20);
}
@Scope注解,是跟@Bean搭配一起使用,主要是标注bean的定义(单例,多例)
@Bean
@Scope("prototype")
public Person person() {
return new Person("xiaoli", 20);
}
另外@Scope注解,在web应用中,还可以指定session级别,和request级别,具体参看标注部分,看名称就应该知道了
@Lazy注解,是懒加载,如果注入的bean是单例的对象,那么在容器创建的时候,就会创建对象,多例对象是在容器创建完成后,调用的时候创建,所以说@Lazy注解,其实是配合单例对象使用的,只有再单例对象被调用的时候,才会创建对象
最后是测试:大家自己测试吧,多例,别名,初始化方法,销毁方法,懒加载等
@Test
public void testImport() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
Person bean = applicationContext.getBean(Person.class);
Object bean2 = applicationContext.getBean("person01");
applicationContext.close();
}