什么是Spring自动装配
自动装配是Spring满足bean依赖的一种方式
spring会在上下文中自己寻找,并自动装配bean的属性
在Spring中有三种装配的方式
1、在xml中显示的配置
2、在java中显示的配置
3、隐式的自动装配bean(最常用的)
搭配环境:一个人有两个宠物
Cat类:
package com.jie.autowired;
public class Cat {
public void cry(){
System.out.println("miao~");
}
}
Dog类:
package com.jie.autowired;
public class Dog {
public void cry(){
System.out.println("wang~");
}
}
Person类:
package com.jie.autowired;
public class Person {
private Dog dog;
private Cat cat;
private String name;
//省略get set方法。。。
@Override
public String toString() {
return "Person{" +
"dog=" + dog +
", cat=" + cat +
", name='" + name + '\'' +
'}';
}
}
基于xml中显示的配置
使用autowired自动装配属性:有byName和byType两种方式:
byName方式:
<?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.xsd">
<bean id="dog" class="com.jie.autowired.Dog" />
<bean id="cat" class="com.jie.autowired.Cat" />
<!--
byName:会自动在上下文中查找和自己对象set方法后面的值对应的 bean id。也就是上面bean的id中的名字,一定要和set方法后面的名字一样
-->
<bean id="person" class="com.jie.autowired.Person" autowire="byName"/>
</beans>
测试代码:
import com.jie.autowired.Person;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test1 {
@Test
public void testPerson(){
ApplicationContext context = new ClassPathXmlApplicationContext("person.xml");
Person person = context.getBean("person", Person.class);
person.getCat().cry(); //调用狗叫的方法
person.getDog().cry(); //调用猫叫的方法
}
}
运行结果:
miao~
wang~
如上演示一样,我们自动装配成功了。
byType方式:
<bean id="dog" class="com.jie.autowired.Dog" />
<bean id="cat" class="com.jie.autowired.Cat" />
<!-- <bean id="cat2" class="com.jie.autowired.Cat" /> 写上这个的话,byType就不知道找哪一个cat类型了-->
<!--
byType: 会自动在上下文中查找和自己对象属性相同的bean,忽略对象bean的 id,但是有一样的类型就bean不行了
-->
<bean id="person" class="com.jie.autowired.Person" autowire="byType"/>
运行结果也打印出了miao~ ,wang~ 证明我们也自动装配成功了。
在java中显示的配置
要想使用注解@Autowired需要注意的事项:
1、需要在pom文件中导入依赖:
<!-- Spring 容器包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework.version}</version>
</dependency>
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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
">
<!-- 启用自动装配注解支持 -->
<context:annotation-config/>
</beans>
修改person.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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--启用注解支持-->
<context:annotation-config/>
<bean id="dog" class="com.jie.autowired.Dog"/>
<bean id="cat" class="com.jie.autowired.Cat"/>
<bean id="person" class="com.jie.autowired.Person"/>
</beans>
修改Person类,使用@Autowired注解的方式自动注入
package com.jie.autowired;
import org.springframework.beans.factory.annotation.Autowired;
public class Person {
@Autowired
private Dog dog;
@Autowired
private Cat cat;
private String name;
//使用@Autowired可以不用写set方法
//省略get方法
@Override
public String toString() {
return "Person{" +
"dog=" + dog +
", cat=" + cat +
", name='" + name + '\'' +
'}';
}
}
运行测试:
miao~
wang~
我们可以看见使用注解方式也自动注入成功了~
@Autowired注解可以使用在属性上,也可以用在set方法上面,还能用在构造方法上面
使用了@Autowired注解就可以不编写set方法了前提是自动装配的属性在IOC容器中存在,且名字符合byName
扩展:
@Nullable 字段被标记了这个注解说明这个字段可以为 null
@Autowired() 中可以写一个属性:reouired = false 也是说明这个属性可以为 null,默认是 true
如果@Autowired()自动装配的环境比较复杂,自动装配无法通过一个注解【@Autowired()】完成的时候我们可以说使用@Qualifier(value=“XXX”)去配置@Autowired()的使用,指定唯一一个bean对象的注入
public class Person {
@Autowired
@Qualifier(value = "dog1")
private Dog dog;
@Autowired
@Qualifier(value = "cat1")
private Cat cat;
}
另外有一个注解能和@Autowired()效果一样,那就是@Resource注解
你可以使用@Resource测试
public class Person {
@Resource //和@Autowired()一样的效果
private Dog dog;
@Resource(name = "cat1") //和name属性和@Qualifier(value = "dog1") 效果一致
private Cat cat;
}
@Autowired()和@Resource的区别:
都是用来自动装配的,都可以放在属性上
@Autowired()通过byType的方式实现,而且必须要求这个对象存在
@Resource()默认通过byName的方式实现,如果找不到名字,则通过byType实现,如果两种都找不到就报错了
隐式的自动装配bean(最常用的)
全部使用注解来实现不需要配置xml文件了,在spring4后,想要使用注解必须导入aop的依赖包
新建一个User类:
package com.jie.autowired2;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
//@Component注解就是将User类加载到spring容器中,类似于配置了一个bean对象
@Component
public class User {
@Value("jie") //@Value注解相当于在property标签中的为属性注入值
private String name;
public void getName(){
System.out.println(this.name);
}
}
接下载配置Config类:
package com.jie.autowired2;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
//这个注解也会被spring容器托管,加载到spring容器中去
// @Configuration代表这个类是一个配置类和xml配置文件一样
//@ComponentScan注解就是扫描包下的所有注解
@Configuration
@ComponentScan("com.jie.autowired2")
public class JieConfig {
/*
注册一个bean,就是相当于我们之前在xml配置文件写的bean
方法的名字就是bean的id,返回值就是bean的class属性
*/
@Bean
public User getUser(){
return new User();
}
//其他的@bean...
}
测试:
@Test
public void testUser() {
//现在我们使用AnnotationConfigApplicationContext注解获取spring上下文JieConfig.class就是我们的主配置类
ApplicationContext context = new AnnotationConfigApplicationContext(JieConfig.class);
//获取刚刚的配置的bean对象
User user = context.getBean("getUser", User.class);
//调用user类中的方法测试是否注入成功
user.getName();
}
结果没问题,输出了jie
jie
要是有多个配置文件,可以使用@import注解在主配置文件中导入其他的配置类
@Configuration
@ComponentScan("com.jie.autowired2")
@Imoprt(userConfig.class) //引入userConfig配置类
//其他的配置类引入...
public class JieConfig {
}