Spring - IOC中对bean的获取和管理以及基于注解的自动装配

2.2.2、实验二:获取bean
①方式一:根据id获取

由于 id 属性指定了 bean 的唯一标识,所以根据 bean 标签的 id 属性可以精确获取到一个组件对象。
上个实验中我们使用的就是这种方式。

②方式二:根据类型获取
@Test
    public void testIOC(){
        //获取IOC容器
        ApplicationContext ioc=new ClassPathXmlApplicationContext("applicationContext.xml");
        //获取bean对象
        HelloWorld  helloWorld= ioc.getBean(Helloworld.class);
        helloworld.saySpring();
    }
③方式三:根据id和类型
@Test
    public void testIOC(){
        //获取IOC容器
        ApplicationContext ioc=new ClassPathXmlApplicationContext("applicationContext.xml");
        //获取bean对象
        HelloWorld  helloWorld=  ioc.getBean("helloworldOne",Helloworld.class);
        helloworld.saySpring();
    }
④注意

当根据类型获取bean时,要求IOC容器中指定类型的bean有且只能有一个
当IOC容器中一共配置了两个:

<bean id="helloworldOne" class="com.atguigu.spring.pojo.HelloWorld"></bean>
<bean id="helloworldTwo" class="com.atguigu.spring.pojo.HelloWorld"></bean>

org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type ‘com.atguigu.spring.pojo.HelloWorld’ available: expected single matching bean but found 2: helloworldOne,helloworldTwo

⑤扩展

如果组件类实现了接口,根据接口类型可以获取 bean 吗?

可以,前提是bean唯一

如果一个接口有多个实现类,这些实现类都配置了 bean,根据接口类型可以获取 bean 吗?

不行,因为bean不唯一

⑥结论

根据类型来获取bean时,在满足bean唯一性的前提下,其实只是看:『对象 instanceof 指定的类
型』的返回结果,只要返回的是true就可以认定为和类型匹配,能够获取到。

2.2.3、实验三:依赖注入之setter注入

简而言之就是为当前类的属性进行赋值

①创建学生类Student
package com.atguigu.spring.pojo;

public class Student {
    private Integer sid;
    private String sname;
    private Integer age;
    private String gender;


    @Override
    public String toString() {
        return "Student{" +
                "sid=" + sid +
                ", sname='" + sname + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                '}';
    }

    public Student(Integer sid, String sname, Integer age, String gender) {
        this.sid = sid;
        this.sname = sname;
        this.age = age;
        this.gender = gender;
    }

    public Student() {
    }

    public Integer getSid() {
        return sid;
    }

    public void setSid(Integer sid) {
        this.sid = sid;
    }

    public String getSname() {
        return sname;
    }

    public void setSname(String sname) {
        this.sname = sname;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }
}

②配置bean时为属性赋值
<bean id="studentOne" class="com.atguigu.spring.bean.Student">
	<!-- property标签:通过组件类的setXxx()方法给组件对象设置属性 -->
	<!-- name属性:指定属性名(这个属性名是getXxx()、setXxx()方法定义的,和成员变量无关)
	-->
	<!-- value属性:指定属性值 -->
	<property name="id" value="1001"></property>
	<property name="name" value="张三"></property>
	<property name="age" value="23"></property>
	<property name="sex" value=""></property>
</bean>
③测试
@Test
public void testDIBySet(){
	ApplicationContext ac = new ClassPathXmlApplicationContext("spring-di.xml");
	Student studentOne = ac.getBean("studentOne", Student.class);
	System.out.println(studentOne);
}

2.2.4、实验四:依赖注入之构造器注入
①在Student类中添加有参构造
public Student(Integer sid, String sname, String gender,Integer age ) {
        this.sid = sid;
        this.sname = sname;
        this.age = age;
        this.gender = gender;
}
②配置bean
<bean id="studentTwo" class="com.atguigu.spring.bean.Student">
	<constructor-arg value="1002"></constructor-arg>
	<constructor-arg value="李四"></constructor-arg>
	<constructor-arg value="33"></constructor-arg>
	<constructor-arg value=""></constructor-arg>
</bean>
③测试
@Test
    public void testDI(){
        ApplicationContext ioc=new ClassPathXmlApplicationContext("spring-ioc.xml");
        Student studentThree = ioc.getBean("studentThree", Student.class);
        System.out.println(studentThree);
    }

2.3、基于注解管理bean

2.3.1、表示组件的常用注解
①注解

@Component:将类标识为普通组件

@Controller:将类标识为控制层组件

@Service:将类标识为业务层组件

@Repository:将类标识为持久层组件

@Controller、@Service、@Repository这三个注解只是在@Component注解 的基础上起了三个新的名字。对于Spring使用IOC容器管理这些组件来说没有区别。

这三个组件知识给开发人员看的

②扫描组件
情况一:最基本的扫描
<context:component-scan base-package="com.atguigu。spring">
</context:component-scan>

在ssm整合中,springMVC扫描控制层

spring扫描其他的全部

情况二:指定要排除的组件
<context:component-scan base-package="com.atguigu">
    <!-- context:exclude-filter标签:指定排除规则 -->
    <!--
        type:设置排除或包含的依据
        type="annotation",根据注解排除,expression中设置要排除的注解的全类名
        type="assignable",根据类型排除,expression中设置要排除的类型的全类名
    -->
	<context:exclude-filter type="annotation"expression="org.springframework.stereotype.Controller"/>
	<!--<context:exclude-filter type="assignable"expression="com.atguigu.controller.UserController"/>-->
</context:component-scan>

情况三:仅扫描指定组件
<context:component-scan base-package="com.atguigu" use-default-filters="false">
    <!-- context:include-filter标签:指定在原有扫描规则的基础上追加的规则 -->
    <!-- use-default-filters属性:取值false表示关闭默认扫描规则 -->
    <!-- 此时必须设置use-default-filters="false",因为默认规则即扫描指定包下所有类 -->
    <!--
        type:设置排除或包含的依据
        type="annotation",根据注解排除,expression中设置要排除的注解的全类名
        type="assignable",根据类型排除,expression中设置要排除的类型的全类名
    -->
	<context:include-filter type="annotation"expression="org.springframework.stereotype.Controller"/>
	<!--<context:include-filter type="assignable"expression="com.atguigu.controller.UserController"/>-->
</context:component-scan>
③组件所对应的bean的id

在我们使用XML方式管理bean的时候,每个bean都有一个唯一标识,便于在其他地方引用。现在使用 注解后,每个组件仍然应该有一个唯一标识。

默认情况
类名首字母小写就是bean的id。例如:UserController类对应的bean的id就是userController。
自定义bean的id
可通过标识组件的注解的value属性设置自定义的bean的id
@Service(“userService”)//默认为userServiceImpl public class UserServiceImpl implements
UserService {}

2.3.2、实验二:基于注解的自动装配
①场景模拟

参考基于xml的自动装配
在UserController中声明UserService对象
在UserServiceImpl中声明UserDao对象

②@Autowired注解

在成员变量上直接标记@Autowired注解即可完成自动装配,不需要提供setXxx()方法。以后我们在项 目中的正式用法就是这样。

@Controller
public class UserController {
	@Autowired
	private UserService userService;
	public void saveUser(){
		userService.saveUser();
	}
}
③@Autowired工作流程

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值