传统的spring是xml与java代码相结合。
xml部分:
<bean id="dog" class="demo.entity.Dog">
<property name="name" value="dog wangwang.."/>
</bean>
<bean id="person" class="demo.entity.Person">
<constructor-arg name="age" value="18"/>
<constructor-arg name="name" value="human"/>
<!-- 装配对象之间的关系-->
<constructor-arg name="pet" ref="dog"/>
</bean>
java部分:
public class Dog{
String name = "dog wangwang..";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Person {
String name;
int age = 18;
Dog pet;
public Person(Dog pet,String name, int age) {
this.name = name;
this.age = age;
this.pet = pet;
}
public Dog getPet() {
return pet;
}
public void setPet(Dog pet) {
this.pet = pet;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
ApplicationContext context = new ClassPathXmlApplicationContext("/spring.xml");
Person person = (Person)context.getBean("person");
System.out.println(person.getName());
System.out.println(person.getAge());
System.out.println(person.getPet().getName());
输出:
human
18
dog wangwang..
一个应用程序有多少个Bean你自己心里没点数??
so。。。
spring2.5引入注解装配,这种方式的装配只要由两部分组成
1.自动扫描:
将你需要的bean纳入spring管理,而spring为纳入的bean主要区分为四大类。消除xml中bean元素的定义。
spring容器对于所有的bean分为了以下四类:
@Component 通用注解,仅标识为spring组件。
@Controller 定义为SpringMvc Controller。
@Repository
1.标识为数据仓库
2.将被@Repository注解的类添加一个通知器,这样就可以捕获mybatis,hibernate等第三方持久层框架相关的异常,然后以spring的非检查型异常形式重新抛出。
@Service 标识为服务。
2.自动装配:
为bean之间建立依赖关系,主要有四种方式装配置。
byName:
按照bean的id来装配,如果没有指定id,id默认为bean的类名,首字母小写,比如bean:CityPerson,默认id为cityPerson。
byType:
寻找类型进行匹配,有多个bean可以匹配的时候,可以标识其中一个类标识为首选bean(将其他的bean设置为primary=false),或者将不需要进行装配的bean进行排除(将其他的bean设置为autowire-condidate=false)
constrictor:
通过构造函数进行装配。
自动匹配:
首先尝试constrictor匹配,否则进行byType尝试.
spring默认关闭这种注解装配方式,因此必须在配置中开启注解装配配置,xml需要加上以下配置。
<!-- 扫描package,将需要的bean纳入spring管理 -->
<context:component-scan base-package="demo.*"/>
<!-- 开启注解装配 -->
<context:annotation-config/>
spring提供以下三种自动装配的注解:
@Autwired
spring自带的注解,可装配null,装配方式为byType,当type匹配多个时,可以将byType注入转换为byName注入,使用@Qualifier来完成转换并缩小bean的范围。
@Inject
java标准 JSR-330,强装配,不可为null,装配方式为byType。当装配多个bean时,将byType注入转换为byName注入,使用@Named缩小bean范围。
@Resource
java标准 JSR-250,强装配,不可为null,先byName,后byType。
spring自带的装配注解 @Auowired
public interface Animal {
String say();
}
@Component
public class Cat implements Animal {
public String say() {
return this.getClass().getName();
}
}
@Component
public class Dog implements Animal {
public String say() {
return this.getClass().getName();
}
}
@Component
public class Person {
@Autowired
private Animal animal;
public Animal getAnimal() {
return animal;
}
public void setAnimal(Animal animal) {
this.animal = animal;
}
}
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
Person person = (Person)context.getBean("person");
System.out.println(person.getAnimal().say());
报错信息如下
spring没有找到相应animal类型,但是cat和dog这两个bean可以匹配上。这时我们缩小bean的范围到cat.代码改为。
@Component
public class Person {
@Autowired
@Qualifier("cat")
private Animal animal;
public Animal getAnimal() {
return animal;
}
public void setAnimal(Animal animal) {
this.animal = animal;
}
}
或者代码改为
@Component
public class Person {
@Autowired
private Animal cat;
public Animal getCat() {
return cat;
}
public void setCat(Animal cat) {
this.cat = cat;
}
}
或者代码改为
@Component
@Primary
public class Cat implements Animal {
public String say() {
return this.getClass().getName();
}
}
@Component
public class Person {
@Autowired
private Animal animal;
public Animal getAnimal() {
return animal;
}
public void setAnimal(Animal animal) {
this.animal = animal;
}
}
三种方法正常输出:
demo.entity.Cat
第一种:缩小bean的范围。
第二种:按照名称来装配,找到id为cat的bean。
第三种:设置Cat为首选bean。
一般来说使用第一种用@Autowired和@Qualifier比较多,后两者比较少。
JSR-330的装配注解基本上可以完全替换spring的注解,这种方式的注解需要引用额外的jar包。
maven依赖为
<!-- https://mvnrepository.com/artifact/javax.inject/javax.inject -->
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
@Inject替换@Autowired,@Named替换@Qualifier,代码改为
@Component
public class Person {
@Inject
@Named("cat")
private Animal animal;
public Animal getAnimal() {
return animal;
}
public void setAnimal(Animal animal) {
this.animal = animal;
}
}
两种注解混用
@Component
@Primary
public class Cat implements Animal {
public String say() {
return this.getClass().getName();
}
}
@Component
public class Person {
@Inject
private Animal animal;
public Animal getAnimal() {
return animal;
}
public void setAnimal(Animal animal) {
this.animal = animal;
}
}
两种都输出:
demo.entity.Cat
最后还有一种JSR-250提供的@Resource注解进行装配,和@Inject不同的是,该注解是在rt包下,因此不需要引用任何其他maven依赖。
@Resource注解首先进行名称匹配,不成功则进行类型匹配,两种匹配都没有找到对应的bean,则抛出异常。
验证先名称,后类型匹配规则,代码改为:
Person类
Cat类没有继承Animal。
继承了Animal的Dog类。
测试代码
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
Person person = (Person)context.getBean("person");
System.out.println(person.getCat().say());
spring先去找了Cat这个类,发现并不是Animal的子类,然后他并没有继续去找Dog类,而是选择了抛出错误信息。很显然,@Resource确实是先名称,后类型的顺序去注入的。
显示指定名称匹配
@Component
public class Person {
@Resource(name = "cat")
private Animal animal;
public Animal getAnimal() {
return animal;
}
public void setAnimal(Animal animal) {
this.animal = animal;
}
}
显示指定类型匹配
@Component
public class Person {
@Resource(type = Cat.class)
private Animal animal;
public Animal getAnimal() {
return animal;
}
public void setAnimal(Animal animal) {
this.animal = animal;
}
}
这时你可以想到我们可以直接在java中作赋值操作。这当然是对的,但是我们也可以通过spring对于基本类型进行注入。而且是动态的。
关于@Value如何动态创建值,请搜索其他相关文章。
//@Component注解的bean被spring扫描到了之后自动纳入spring管理。
@Component
public class Person {
//通过spring的@Value动态注入属性值
@Value("human")
String name;
@Value("18")
int age = 18;
//自动注入,建立bean之间的依赖关系
@Autowired
Dog pet;
// public Person(Dog pet,String name, int age) {
// this.name = name;
// this.age = age;
// this.pet = pet;
// }
public Dog getPet() {
return pet;
}
public void setPet(Dog pet) {
this.pet = pet;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
总结一下:
1.spring装配有四种方式,分别是名称匹配,类型匹配,构造函数匹配,自动匹配(先构造函数,后type)。
2.spring注解装配提供三种方式,分别是spring自带的@Autowired,JSR-330的@Inject,JSR-250的@Resource。
3.@Autowired可装配null,先按照type进行匹配,匹配多个时,可匹配@Qualifier注解进行bean的范围锁定。
4.spring提供@Primary将bean标记为首选bean。
5.@Inject不可装配null,和@Autowired一样按照type进行装配,匹配多个时用@Named进行bean的范围锁定。
6.@Resource不可装配null,先按照名称匹配,否则按照类型匹配。
资料:
http://blog.youkuaiyun.com/u012734441/article/details/51706504
http://blog.youkuaiyun.com/baple/article/details/17891755
http://blog.youkuaiyun.com/ethanwhite/article/details/51879871