在Spring中,提供了两种方式来让Spring IoC容器发现Bean:
- 组件扫描:通过定义资源的方式,让Spring IoC容器扫描对应的包,从而把Bean装配进来。
- 自动装配:通过注解定义,使得一些依赖关系可以通过注解完成。
注解的作用:
使用注解的方式可以减少XML的配置,注解功能更为强大,它既能实现XML的功能,也提供了自动装配的功能,采用了自动装配后,程序员所需要做的决断就少了,更加有利于对程序的开发,这就是“约定优于配置”的开发原则。
通过扫描和自动装配,大部分的工程都可以用Java配置完成,而不是XML,这样可以有效减少配置和引入大量XML,但是不是全部以注解的方式去实现。因为不使用XML也存在着一定的弊端,比如系统存在多个公共的配置文件(比如多个properties和XML文件),如果写在注解里,那么那些公共资源的配置就会比较分散了,这样不利于统一的管理,又或者一些类来自于第三方,而不是我们系统开发的配置文件,这时利用XML的方式来完成会更加明确一些,因此目前企业所流行的方式是,以注解为主,以XML为辅。
步骤:
- 首先要在Spring中配置开启注解扫描<context:component-scan base-package=” ”></ context:component-scan>
- 在具体的类上加上具体的注解
- Spring 中通常使用的几种装配方式进行bean的装配
- @Component注解对类进行标注,一般用于自定义组件,它可以被Spring容器识别,把普通类实例化到spring容器中,Spring容器将自动将类转换为容器管理的Bean。相当于配置文件中的<bean id="" class=""/> 如:
- Spring提供了三个功能和@Component等效的注解。
- @Repository 该注解用于将数据访问层(Dao层)的类标识为Bean,即注解数据访问层Bean,对DAO实现类(mapper)进行注解,其功能与@Componet相同
- @Service 该注解用于标注一个业务逻辑组件类(Service层),对service实现类进行注解,其功能与@Component相同
- @Controller 该注解用于标注一个控制器组件类(SpringMVC的Controller),对web层Controller实现类进行注解,其功能与@Componet相同
- @Autowired 该注解可以对类成员变量、方法及构造方法进行标注,完成自动装配的功能。默认按照Bean的类型进行装配。
-
注解方式注入引用类型属性
//会根据类型自动注入 @Autowired private UserService userservice;
//@Autowired可以对类成员变量的set方进行注解。 //对set方法使用注解,UserDao的实例就会被注入进来 @Autowired public void setUserdao(UserDao userdao){ this.userdao=userdao; }
问题:@Autowired默认按类型匹配的方式,在容器中查找匹配的Bean,当有且只有一个匹配的Bean时,Spring将其注入到@Autowired注解的变量中。但是如果容器中有超过一个以上的匹配Bean时,例如有两个UserService类型的Bean,这时就不知道将哪个Bean注入到变量中,就会出现异常。
为了解决这个问题,Spring可以通过@Qualifier注解来注入指定Bean的名称。
-
@Qualifier 该注解与@Autowired注解配合使用。当@Autowired注解需要按照名称来装配注入时,需要和该注解一起使用,Bean的实例名称由@Qualifier注解的参数指定
public class UserAction { @Autowired //指定指定Bean的名称 @Qualifier("userservice") private UserService userservice; }
还有一种更为便捷的注解方式注入属性@Resource,相当于@Autowired 和@Qualifier一起使用
-
@Resource 该注解与@Autowired的功能一样,区别在于该注解默认是按照名称来装配的,只有当找不到与名称匹配的Bean时才会按照类型来装配注入;而@Autowired默认按照Bean的类型进行装配,如果想按照名称来装配注入,则需要和@Qualifier注解一起使用。 @Resource注解有两个属性—name和type。name属性指定Bean实例名称,即按照名称来装配注入;type属性指定Bean类型,即按照Bean的类型进行装配。
-
注解方式注入一般类型属性。Spring为我们提供了注解 @value,用于对一般属性注入,可以不用提供set方法
@Value("Tom") private String nmae; @Value("22") private int age; //它是通过反射的Field赋值,破坏了封装性
提供set方法的也可以这样注入
@Value("Tom") Public void setName(String name){ this.name = name; } //通过set方法赋值,推荐使用.
然而在实际开发者中,尽管实际是破坏了对象的封装性,但开发者还是喜欢用第一种方式注入属性。