【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

 

posted @   王广元  阅读(48)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
分享到:
点击右上角即可分享
微信分享提示