【Spring】学习笔记07-Bean自动装配
自动装配是Spring满足bean依赖的一种方式!
Spring会在上下文中自动寻找,并自动给bean装配属性!
在Spring中有三种装配的方式:
1.在xml中显式的配置
pojo类
public interface makevoice { public void makevoice(); }
/** * @author 王广元 */ @Data public class Cat implements makevoice{ @Override public void makevoice() { System.out.println("miao miao"); } }
/** * @author 王广元 */ @Data public class Dog implements makevoice{ @Override public void makevoice() { System.out.println("wang wang"); } }
@Data
@NoArgsConstructor
public class People {
private Cat cat;
private Dog dog;
private String 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:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="cat" class="com.wang.pojo.Cat"/> <bean id="dog" class="com.wang.pojo.Dog"/> <bean id="people" class="com.wang.pojo.People" p:cat-ref="cat" p:dog-ref="dog" p:name="王广元"/> </beans>
单元测试
@Test
public void test01(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
Object people = context.getBean("people");
System.out.println(people.toString());
}
//测试结果:People(cat=Cat(), dog=Dog(), name=王广元)
2.在java中显示配置
3.隐式地自动装配bean【重要】
1.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" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="cat" class="com.wang.pojo.Cat"/> <bean id="dog" class="com.wang.pojo.Dog"/> <bean id="people1" class="com.wang.pojo.People" autowire="byName"> <property name="name" value="poeple1_autowire_byName"/> </bean> </beans>
我们通过设置autowire参数,此时为byName,通过注册bean的id实现自动装配,Spring容器会自动在容器上下文中查找和自己对象set方法后面的值对应的bean id,
找到id=cat and id=dog的bean,并将其装配到id=people1的bean中
单元测试
@Test public void test03(){ ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml"); People people1 = (People) context.getBean("people1"); System.out.println(people1.toString()); }
//测试结果:People(cat=Cat(), dog=Dog(), name=poeple1_autowire_byName)
2.byType
<!-- bytype:会自动查找容器上下文中,和自己对象属性相同的bean--> <bean id="people2" class="com.wang.pojo.People" autowire="byType"> <property name="name" value="people+autowire_bytype"/> </bean>
缺点:bean上下文中只允许注册class类的一个bean,当注册多个时,会报错
单元测试
@Test public void test02(){ ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml"); People people2 = (People) context.getBean("people2"); System.out.println(people2.toString()); }
小结:
- byname的时候,需要保证所有bean的id唯一,并且这个bean需要和自动注入的属性的set的值保持一致!
- byname的时候,需要保证所有bean的class唯一,并且这个bean需要和自动注入的属性的类型保持一致!
4.使用注解实现自动装配
Are annotations better than XML for configuring Spring?
The introduction of annotation-based configuration raised the question of whether this approach is “better” than XML. The short answer is “it depends.”
The long answer is that each approach has its pros and cons, and, usually, it is up to the developer to decide which strategy suits them better.
Due to the way they are defined, annotations provide a lot of context in their declaration, leading to shorter and more concise configuration.
However, XML excels at wiring up components without touching their source code or recompiling them.
Some developers prefer having the wiring close to the source while others argue that annotated classes are no longer POJOs and,
furthermore, that the configuration becomes decentralized and harder to control.
No matter the choice, Spring can accommodate both styles and even mix them together. It is worth pointing out that through its JavaConfig option,
Spring lets annotations be used in a non-invasive way, without touching the target components source code and that, in terms of tooling,
all configuration styles are supported by the Spring Tools for Eclipse.
JDK1.5支持的注解,Spring就支持注解了
要使用注解须知:
导入约束
xmlns:context="http://www.springframework.org/schema/context"
配置注解的支持
<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 https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <context:annotation-config/> </beans>
@Autowired
直接在属性上使用(也可以应用在set方法上),
使用Autowired我们可以不用编写set方法了,前提是你这个自动装配的属性在IOC(Spring)容器中存在,且符合名字(byType)
public @interface Autowired { boolean required() default true; }
required=false,允许bean实例地属性值为null
测试实例:
pojo类
@Data @NoArgsConstructor public class People { //如果显示地定义了Autowired地requiref属性为false,证明这个对象可以为null @Autowired(required = false) private Cat cat; @Autowired(required = false) private Dog dog; private String name; public People(@Nullable String name) { this.name = name; } }
单元测试
@Test public void test05(){ ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml"); People people3 = (People) context.getBean("people3"); System.out.println(people3.toString()); }
//测试结果
//People(cat=null, dog=null, name=测试@Autowired注解)
@Autowired+@Qu
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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <context:annotation-config/> <bean id="cat1" class="com.wang.pojo.Cat"/> <bean id="dog1" class="com.wang.pojo.Dog"/> <bean id="dog2" class="com.wang.pojo.Dog"/> <bean id="people3" class="com.wang.pojo.People"> <property name="name" value="测试@Autowired注解"/> </bean> </beans>
当存在多个相同class的bean存在于Spring容器中,我们可以使用@Qualifier(value=bean_id)手动指定相应属性注入的bean
@Data @NoArgsConstructor public class People { //如果显示地定义了Autowired地requiref属性为false,证明这个对象可以为null @Autowired(required = false) private Cat cat; @Autowired(required = false) @Qualifier(value = "dog2") private Dog dog; private String name; public People(@Nullable String name) { this.name = name; } }
如果@Autowired自动装配的环境比较复杂,自动装配无法通过一个注解【@Autowired】完成时,我们可以使用@Qualifier(value="xxx")去配置@Autowired的使用。
@Resource
POJO类
@Data @NoArgsConstructor public class People { //如果显示地定义了Autowired地requiref属性为false,证明这个对象可以为null @Resource(name="cat1") private Cat cat; @Resource private Dog dog; private String name; public People(@Nullable String name) { this.name = 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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <context:annotation-config/> <bean id="cat1" class="com.wang.pojo.Cat"/> <bean id="cat2" class="com.wang.pojo.Dog"/> <bean id="dog1" class="com.wang.pojo.Dog"/> <bean id="dog2" class="com.wang.pojo.Dog"/> <bean id="people3" class="com.wang.pojo.People"> <property name="name" value="测试@Autowired注解"/> </bean> </beans>
单元测试
@Test public void test05(){ ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml"); People people3 = (People) context.getBean("people3"); System.out.println(people3.toString()); } 警告: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'people3': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.wang.pojo.Dog' available: expected single matching bean but found 3: cat2,dog1,dog2 org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'people3': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.wang.pojo.Dog' available: expected single matching bean but found 3: cat2,dog1,dog2
此时beans.xml中存在多个Cat,Dog的注册bean,但id都不符合People类中set方法的值,因此会报错、
我们将cat1,dog1的beanid改为cat,dog
<bean id="cat" class="com.wang.pojo.Cat"/> <bean id="dog" class="com.wang.pojo.Dog"/>
此时单元测试一切正常(测试结果)
People(cat=Cat(), dog=Dog(), name=测试@Autowired注解)
进程已结束,退出代码为 0
同样@Resource(name="xxx")可以通过name显示地指定bean
@Autowired和@Resource的区别
相同点:
都是作用于自动装配的
不同点:
@Autowired 是先 bytype然后byname(当存在多个相同class的bean时,需要借助@Qualifier注解手动指定相应的bean)
@Resource 也是先bytype然后byname
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现