转自:http://blog.csdn.net/cpf2016/article/details/45582399
1.xml中配置bean
假如我们现在有3个类,Boss、Office、Car,这3个类需要在Spring容器中配置为bean
- public class Office {
- private String officeNo =”001”;
- //省略 get/setter
- @Override
- public String toString() {
- return "officeNo:" + officeNo;
- }
- }
- public class Car {
- private String brand;
- private double price;
- // 省略 get/setter
- @Override
- public String toString() {
- return "brand:" + brand + "," + "price:" + price;
- }
- }
- public class Boss {
- private Car car;
- private Office office;
- // 省略 get/setter
- @Override
- public String toString() {
- return "car:" + car + "\n" + "office:" + office;
- }
- }
- <?xml version="1.0" encoding="UTF-8" ?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
- <bean id="boss" class="com.baobaotao.Boss">
- <property name="car" ref="car"/>
- <property name="office" ref="office" />
- </bean>
- <bean id="office" class="com.baobaotao.Office">
- <property name="officeNo" value="002"/>
- </bean>
- <bean id="car" class="com.baobaotao.Car" scope="singleton">
- <property name="brand" value=" 红旗 CA72"/>
- <property name="price" value="2000"/>
- </bean>
- </beans>
测试代码如下:
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class AnnoIoCTest {
- public static void main(String[] args) {
- String[] locations = {"beans.xml"};
- ApplicationContext ctx =
- new ClassPathXmlApplicationContext(locations);
- Boss boss = (Boss) ctx.getBean("boss");
- System.out.println(boss);
- }
- }
2.@Autowired
(1)要求
Spring通过一个BeanPostProcessor对@Autowired进行解析,要使@Autowired起作用,则必须在Spring容器中声明AutowiredAnnotationBeanPostProcessor的Bean
- <!-- 该 BeanPostProcessor 将自动起作用,对标注 @Autowired 的 Bean 进行自动注入 -->
- <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
如果是在成员变量上使用的话:因为是直接使用反射对bean中的私有成员变量进行注入的,所以使用了@Autowired注解之后,可以直接删除setter方法
(2)成员变量上使用
- public class Boss {
- @Autowired
- private Car car;
- @Autowired
- private Office office;
- @Override
- public String toString() {
- return "car:" + car + "\n" + "office:" + office;
- }
- }
- <?xml version="1.0" encoding="UTF-8" ?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
- <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
- <bean id="boss" class="com.mycompany.app.Boss">
- </bean>
- <bean id="office" class="com.mycompany.app.Office">
- <property name="officeNo" value="002"/>
- </bean>
- <bean id="car" class="com.mycompany.app.Car" scope="singleton">
- <property name="brand" value=" 红旗 CA72"/>
- <property name="price" value="2000"/>
- </bean>
- </beans>
car:brand: 红旗 CA72,price:2000.0
office:officeNo:002
(3)set方法上使用
- package com.mycompany.app;
- import org.springframework.beans.factory.annotation.Autowired;
- public class Boss {
- private Car car;
- private Office office;
- @Autowired
- public void setCar(Car car) {
- this.car = car;
- }
- @Autowired
- public void setOffice(Office office) {
- this.office = office;
- }
- @Override
- public String toString() {
- return "car:" + car + "\n" + "office:" + office;
- }
- }
这时,@Autowired将查找被标注的方法的传入参数类型的bean,并调用方法自动注入这些bean
(4)构造方法上使用
- package com.mycompany.app;
- import org.springframework.beans.factory.annotation.Autowired;
- public class Boss {
- private Car car;
- private Office office;
- @Autowired
- public Boss(Car car, Office office) {
- super();
- this.car = car;
- this.office = office;
- }
- @Override
- public String toString() {
- return "car:" + car + "\n" + "office:" + office;
- }
- }
3.@Qualifier
(1)引入及作用
当我们在Spring容器中配置了2个类型为Office类型的bean,当对Boss的office成员变量进行自动注入时,Spring容器将无法确定到底使用哪一个bean,就会发生异常。
- <bean id="boss" class="com.mycompany.app.Boss">
- </bean>
- <bean id="office1" class="com.mycompany.app.Office">
- <property name="officeNo" value="002"/>
- </bean>
- <bean id="office2" class="com.mycompany.app.Office">
- <property name="officeNo" value="004"/>
- </bean>
- Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.mycompany.app.Office] is defined: expected single matching bean but found 2: [office1, office2]
Spring中允许我们通过@Qualifier注释指定注入bean的名称,这样歧义就消除了,可以通过如下方法解决异常
- package com.mycompany.app;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.beans.factory.annotation.Qualifier;
- public class Boss {
- @Autowired
- private Car car;
- @Autowired
- @Qualifier("office1")
- private Office office;
- @Override
- public String toString() {
- return "car:" + car + "\n" + "office:" + office;
- }
- }
4.@Resource
(1)作用
@Resource作用相当于@Autowired,只不过 @Autowired按byType自动注入,@Resource按byName自动注入 。@Resource有两个比较重要的属性:name和type,Spring将@Resource注释的name属性解析为bean的名字,而type属性解析为bean的类型。
所以,如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果不指定name和type,则将通过反射来使用byName自动注入
(2)使用要求
1)@Resource位于common-annotation.jar中,因此在使用之前必须要导包2)在配置文件中加入:
- <bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/>
(3)例子
- public class Boss {
- @Resource
- private Car car;
- @Resource
- private Office office;
- @Override
- public String toString() {
- return "car:" + car + "\n" + "office:" + office;
- }
- }
5.spring中隐式注册注解
使用这些注解时需要在配置文件中导入很多配置,这样会导致配置文件混乱,所以spring提供了一个方法,可以隐式注册这些annotation
- <context:annotation-config/>
- <?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"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context-2.5.xsd">
- <context:annotation-config/>
- <bean id="boss" class="com.mycompany.app.Boss">
- </bean>
- <bean id="office" class="com.mycompany.app.Office">
- <property name="officeNo" value="002"/>
- </bean>
- <bean id="office2" class="com.mycompany.app.Office">
- <property name="officeNo" value="004"/>
- </bean>
- <bean id="car" class="com.mycompany.app.Car" scope="singleton">
- <property name="brand" value=" 红旗 CA72"/>
- <property name="price" value="2000"/>
- </bean>
- </beans>
AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、PersistenceAnnotationBeanPostProcessor 以及equiredAnnotationBeanPostProcessor
6.@Component
(1)引入
虽然我们可以通过@Autowired或者@Resource在bean类中使用自动注入功能,但是bean还是在xml文件中通过<bean>进行了定义——也就是说,在xml配置文件中定义bean,通过@Autowired或者@Resource为bean的成员变量、方法、构造方法入参提供自动注入的功能。那么能否也通过注释定义bean,从xml配置中完全移除bean定义的配置呢?答案是肯定的。我们通过@Component注解就可以达到这个目标了。
实际上共有四种注解实现了这种功能@Component、@Repository、@Controller、@Service,功能完全相同,只是应用于不同的层次
@Component:是一个泛化的概念,仅仅表示是一个bean,可以用在任何层次
@Service:通常用在业务层,功能与@Component相同
@Controller:通常用在控制层,功能与@Component相同
@Repository:通常用在dao层,功能与@Component相同
(2)配置
1)需要指定扫描的包,这样的话spring就可以自动扫描指定包下带@Component(或其他三个)注解的类,并生成bean
- <context:component-scan base-package="com.mycompany.app"/>
2)需要添加命名空间
- <?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"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context-2.5.xsd">
- package com.mycompany.app;
- import javax.annotation.Resource;
- import org.springframework.stereotype.Component;
- @Component
- public class Boss {
- @Resource
- private Car car;
- @Resource
- private Office office;
- @Override
- public String toString() {
- return "car:" + car + "\n" + "office:" + office;
- }
- }
- package com.mycompany.app;
- import org.springframework.stereotype.Component;
- @Component
- public class Car {
- private String brand = "红旗 CA72";
- private double price = 2000;
- @Override
- public String toString() {
- return "brand:" + brand + "," + "price:" + price;
- }
- public String getBrand() {
- return brand;
- }
- public void setBrand(String brand) {
- this.brand = brand;
- }
- public double getPrice() {
- return price;
- }
- public void setPrice(double price) {
- this.price = price;
- }
- }
- package com.mycompany.app;
- import org.springframework.stereotype.Component;
- @Component
- public class Office {
- private String officeNo ="001";
- public String getOfficeNo() {
- return officeNo;
- }
- public void setOfficeNo(String officeNo) {
- this.officeNo = officeNo;
- }
- @Override
- public String toString() {
- return "officeNo:" + officeNo;
- }
- }
(4)@Scope
@Scope注解可以和@Component注解配合使用,用来指定bean的scope。
默认是singleton,也就是整个应用使用同一个实例;如果使用prototype,则spring每次getBean都会拿到新的bean