相对于xml配置bean,java注解配置方式,更简单、快捷,且让人一目了然,类型安全,但是改已实现的类比xml困难。
而xml方式则是松耦合,bean的关系都在一个文件,比较容易理清关系,但是它的类型不安全,而且配置较冗长。
目前更推荐用java注解配置。

一些内置注解介绍

  • @Component:这个注解是用于将一个pojo(普通java对象的缩写,可以理解为一个class)声明为Bean。可以加参数@Component("mybean"),这样这个bean的id就是mybean,否则就是class的名字。相当于@Named,但是不推荐用@Named
  • @ComponentScan:这个注解与@Component@Autowired配套,使用了这个注解就可以扫描包里的@Component,将声明的Bean加入IoC容器中。

它有几个可输入的参数:

  • value:要扫描的包。
  • basePackageClasses:要扫描的类
  • includeFilters:它的值应该是一个集合,表示包含这些组件
  • excludeFilters:它的值也是集合,表示不包含的组件
  • @Autowired:这个注解可以自动装配bean,但是必须要有前两个注解。与@Inject差异不大,可互换。
  • @Bean:它与@Component有相同的作用,将一个pojo声明为bean,但是@Bean是用于方法,将一个方法返回的pojo声明为bean。将pojo的名字作为bean的id,也可以用name=“”来设置其id。
  • @Configuration:这个注解将class声明为配置类,如果要用自动装配,那么就要与@ComponentScan一起使用。如果不自动装配,那么就要在class里把bean之间的关系描述出来。
  • @Import:导入外部的java配置。
  • @ImportResource:导入外部的xml的配置。
  • @Profile:检测参数表示的环境有没有被激活,只有当相应环境激活后,才会装配它描述的bean。
  • @ActiveProfile:用于激活环境。
  • @Primary:描述最先选择的bean。当有多个bean都符合装配条件,则此注释描述的bean优先装配。但是只能有一个bean被描述,多了还是会产生歧义。
  • @Qualifier:此注解成对使用且需要指定限定符(即“()”里的值),当bean被此注解描述,且装配的方法也有此注解,同时限定符一致,则发生歧义时选择一致的bean装配。

因为同一个条目不允许出现多个相同类型的注解,所以由这个注解引申出一种自定义注解:

@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Qualifier public @interface Example{}

@Example就可以代替@Qualifier

  • @Scope:用于描述bean的作用域。

bean的作用域有四种:

  • singleton:应用中只会有一个,不会多次创建。
  • prototype:每次注入、spring上下文获取都会创建。
  • session:一个会话只创建一个。
  • request:每次request请求时创建。
  • 声明时可以用@Scope("prototype"),但是不够安全,最好使用@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
  • 同时在使用session类型的bean时有一些问题,如在网上购物的购物车,每个会话都会有一个购物车,但是我并不想为每一个购物车都写一个处理方法,于是我就要选择注入。但是我怎么能让相应的购物车注入到这个方法中呢,这时就要用到@Scope的一个参数——proxyMode。
  • proxyMode = ScopedProxyMode.INTERFACES就将购物车注入到一个作用域代理处,代理将把这个购物车委托给相应的处理方法。

自动装配示例

配置文件
@Configuration
@ComponentScan
public class Config{
}
IceCream的bean文件
@Component
public class IceCream implements Desserts{
	private String type = "巧克力冰淇淋";
	
	public void eat(){
		System.out.print("巧克力味很好吃");
	}
}
public interface Desserts{
	void eat();
}
People的bean文件
@Component
public class People{
	private Desserts dessert;
	
	@Autowired
	public People(Desserts dessert){
		this.dessert = dessert;
	}
	
	public void eatDessert(){
		dessert.eat();
	}
}
Main类
public class Main {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
        People people = context.getBean(People.class);
        people.eatDessert();
    }
}

手动配置示例

配置文件
@Configuration
public class Config{
	@Bean
	public Desserts getDesserts(){
		return new IceCream();
	}
	
    @Bean
	public People getPeople(){
		return new People(getDesserts());
	}
}
bean文件
@Component
public class IceCream implements Desserts{
	private String type = "巧克力冰淇淋";
	
	public void eat(){
		System.out.print("巧克力味很好吃");
	}
}
public interface Desserts{
	void eat();
}
@Component
public class People{
	private Desserts dessert;
	
	public People(Desserts dessert){
		this.dessert = dessert;
	}
	
	public void eatDessert(){
		dessert.eat();
	}
}