传统的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.csdn.net/u012734441/article/details/51706504
http://blog.csdn.net/baple/article/details/17891755
http://blog.csdn.net/ethanwhite/article/details/51879871