@Autowired、@Resource和@Service注解

参考:http://www.cnblogs.com/xrq730/p/5313412.html
http://blog.youkuaiyun.com/baple/article/details/17891755

什么是注解

传统的Spring做法是使用.xml文件来对bean进行注入或者配置aop、事物,这么做有两个缺点:
(1)如果所有的内容都配置在.xml文件中,那么.xml文件将会十分庞大;如果按需求分开.xml文件,那么.xml文件又会非常多总之这将导致配置文件的可读性和可维护性变得很低
(2)在开发中.java文件和.xml文件之间不断切换,是一件麻烦的事,同时这种思维上的不连贯也会降低开发的效率
为了解决这两个问题,Spring引入了注解,通过"@XXX"的方式,让注解与Java Bean紧密结合,既大大减少了配置文件的体积,又增加了Java Bean的可读性与内聚性。本次主要讲解@Autowired、@Resource和@Service注解

不使用注解

先定义三个Bean

public class Monkey {
private String monkeyName = "MonkeyKing";
    
    public String toString()
    {
        return "MonkeyName:" + monkeyName;
    }
}
public class Tiger {
	 private String tigerName = "TigerKing";
	    
	    public String toString()
	    {
	        return "TigerName:" + tigerName;
	    }

}
public class Zoo {
	private Tiger tiger;
    private Monkey monkey;
public void setTiger(Tiger tiger)
    {
        this.tiger = tiger;
    }
    
    public void setMonkey(Monkey monkey)
    {
        this.monkey = monkey;
    }
    
    public Tiger getTiger()
    {
        return tiger;
    }
    
    public Monkey getMonkey()
    {
        return monkey;
    }
    
    public String toString()
    {
        return tiger + "\n" + monkey;
    }
}

applicationContext.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"
	 xsi:schemaLocation="http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/context 
           http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    <bean id="zoo" class="com.spring.ioc.Zoo">
    	<property name="tiger" ref="t"></property>
    	<property name="monkey" ref="m"></property>
    </bean>
    <bean id="t" class="com.spring.ioc.Tiger"></bean>
    <bean id="m" class="com.spring.ioc.Monkey"></bean>
</beans>

Test

public static void main(String[] args) {
		ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
		Zoo z=(Zoo)ac.getBean("zoo");
		System.out.println(z.toString());
	}

输出:
TigerName:TigerKing
MonkeyName:MonkeyKing

使用@Autowired

默认按照类型自动装配注入,如果需要进行接口注入,也就是说可能遇到这种情况,当你创建多个具有相同类型的 bean 时,并且想要用一个属性只为它们其中的一个进行装配,比如实现同一个接口的不同类,这时候需要结合@Qualifier使用,这时候是按照名称装配
###按照类型装配
把上面的Zoo.java中的set/get方法去掉

public class Zoo {
	@Autowired
	private Tiger tiger;
	@Autowired
    private Monkey monkey;
    public String toString()
    {
        return tiger + "\n" + monkey;
    }
}

applicationContext.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"
	 xsi:schemaLocation="http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/context 
           http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    
    <context:component-scan base-package="com.spring.car"></context:component-scan>
    <bean id="zoo" class="com.spring.ioc.Zoo"></bean>
   
</beans>

测试代码不变,输出结果也是:
TigerName:TigerKing
MonkeyName:MonkeyKing

注意:上面的applicationContext有关Tiger和Cat的定义必须要定义,否则会报错,因为@Autowired注解要去寻找的是一个Bean,Tiger和Monkey的Bean定义都给去掉了,自然就不是一个Bean了,Spring容器找不到就抛出异常。
如果不想要抛出异常,需要在@Autowired加上required=false:

public class Zoo {
	@Autowired(required=false)
	private Tiger tiger;
	@Autowired(required=false)
    private Monkey monkey;
    public String toString()
    {
        return tiger + "\n" + monkey;
    }
}

这个时候尽管没有Tiger和Cat的两个bean,也只是输出两个null不会抛出异常
###按照名称装配
首先定义一个接口

public interface Car {
	public String name();
}

然后定义两个实现类:

public class BMW implements Car{

	public String name() {
		// TODO Auto-generated method stub
		return "BMW";
	}
}
public class BenC implements Car{

	public String name() {
		// TODO Auto-generated method stub
		return "BenC";
	}

}

实现一个工厂类:

public class CarFactory {
	@Autowired
	private Car car;
	public String toString()
    {
        return car.name();
    }
}
<?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-3.0.xsd
           http://www.springframework.org/schema/context 
           http://www.springframework.org/schema/context/spring-context-3.0.xsd">
           
   <context:component-scan base-package="com.spring.car"></context:component-scan>
   <bean id="cf" class="com.spring.car.CarFactory"></bean>
   <bean id="bMW" class="com.spring.car.BMW"></bean>
	<bean id="benz" class="com.spring.car.BenC"></bean>
</beans>

显然如果只是按照上面这样写肯定会报错,因为无法识别Car到底对应的是哪个实现类,这时候就要用到@Qualifier,让它指明是哪一个实现类,在@Qualifier后面的是对应bean的名字

public class CarFactory {
	@Autowired
	@Qualifier("bMW")
	private Car car;
	public String toString()
    {
        return car.name();
    }
}

执行结果:
BMW

使用@Resource

@Resource和@Autowired功能类似,但是也有区别(后面说)
在使用@Resource的时候要导入包common-annotations.jar,否则会报错
上面的CarFactory可以写成这样:

ublic class CarFactory {
	@Resource(name="bMW")
	private Car car;
	public String toString()
    {
        return car.name();
    }
}

其他都不变,也能得到预期结果

@Autowired和@Resource的区别:
(1)@Resource默认按照名称装配,可以通过name属性指定,如果没有指定name属 性,当注解标注在字段上,就会默认按照被标注字段的类型进行注入(比如前面的Zoo的Tiger变量,如果使用@Resource,没有指定name属性,name就会按照Tiger类型寻找bean),当注解标注在属性的setter方法上,即默认取属性名作为bean名称寻找 依赖对象
(2)@Autowired默认按照类型装配,按照类型装配的bean必须存在否则报错,可以通过使用required=false避免报错。
(3)当创建多个具有相同类型的 bean 时,并且想要用一个属性只为它们其中的一个进行装配(比如实现同一个接口的不同类),使用@Autowired和Qualifier的组合,也可以使用@Resource,这时两者是等效的
(4)@Resource注解是又J2EE提供,而@Autowired是由spring提供,故减少系统对spring的依赖建议使用 @Resource的方式;
(5)@Resource和@Autowired都可以书写标注在字段或者该字段的setter方法之上

使用@Service

@Service可以自动把被标注的类声明为一个bean
以前面的Car举例,BenC和BMW前面都加一个@Service

@Service
public class BMW implements Car{

	public String name() {
		// TODO Auto-generated method stub
		return "BMW";
	}
}
@Service
public class BenC implements Car{

	public String name() {
		// TODO Auto-generated method stub
		return "BenC";
	}
}

CarFactory也要加:

@Service
public class CarFactory {
	@Autowired
	@Qualifier("benC")
	private Car car;
	public String toString()
    {
        return car.name();
    }
}

applicationContext.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"
	 xsi:schemaLocation="http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/context 
           http://www.springframework.org/schema/context/spring-context-3.0.xsd">   
   <context:component-s
   can base-package="com.spring.car"></context:component-scan> 
</beans>

测试:

public class Test {
	public static void main(String[] args) {
		ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
		CarFactory cf=(CarFactory)ac.getBean("carFactory");//注意这里要把前面写的getBean("cf")改成getBean("carFactory")
		System.out.println(cf.toString());
	}
}

输出:
BenC

注意:@Service把被注解的类声明为bean,默认的bean的id是类名首字母小写,其他的不变,但是有一个发现就是我用BMW测试的时候,bean的id是BMW,所以如果全是大写,bean的id和类名相同。
当然,bean的id可以按照我们自己的意愿自己改变,比如CarFactory的bean的id我仍然改为cf:

@Service("cf")
public class CarFactory {
	......
}

测试:

public class Test {
	public static void main(String[] args) {
		......
		CarFactory cf=(CarFactory)ac.getBean("cf");
		System.out.println(cf.toString());
	}
}

仍然能得到预期结果

补充

从这里可以看出@Autowired等注解是为了方便维护bean之间的关系而产生的,如果没有这些注解,那么每次要定义一个包含很多个其他bean的bean(比如上面的zoo包含了Monkey和Tiger),都放到xml文件里面的话,写起来会非常崩溃,在大型项目里面,一个bean可能会被多个其他文件引用,如果每次引用都在xml文件里面定义一遍,写起来和后期维护都是非常麻烦的,有了这些注解,只需要在需要引用其他bean的时候引入就可以了,非常方便。

但是有一个前提是,这些注解方便其他bean的引入,但是引入其他bean的类本身一定要是一个已经被定义的bean,什么意思呢,比如上面Zoo Monkey Tiger的例子,如果我这样写:

ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
		//Zoo z=(Zoo)ac.getBean("zoo");
		Zoo z = new Zoo();
		System.out.println(z.toString());

最后得到的结果是这样的:
在这里插入图片描述
也就是说,tiger和monkey并没有被注入进来,因为你new一个Zoo的时候,这个时候的实例就不是我们xml中定义的bean了,这个bean是你自己new出来的,不是同一个东西,所以这个时候的monkey和tiger属性并没有被初始化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值