相对于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();
}
}