spring创建对象的范围,生命周期,依赖注入注解方式的IOC和DI

本文深入解析Spring框架中IOC容器的运作原理,探讨对象创建的范围、生命周期,以及依赖注入的各种方式,包括set注入、构造注入、p/c名称空间注入、复杂数据类型注入和注解方式的IOC与DI。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.spring创建对象的范围

1.1关于单例和多例的介绍

单例: 内存中只有一个对象,每次获取到该对象的地址值一样.

多例:内存中的每个对象都是一个新的对象,他们的地址值都不同.

spring默认的情况下创建的对象都是单例的. (每次返回的对象都是同一个)
默认scope=singleton

1.1.1单例代码结果演示

代码

  <!--2,通过无参构造创建对象-->
    <bean id="user01" class="com.sen.ioc.Demo02_User" ></bean>

结果

在这里插入图片描述

1.1.2多例代码结果演示

代码

  <!--2,通过无参构造创建对象-->
    <bean id="user01" class="com.sen.ioc.Demo02_User" scope="prototype" ></bean>

结果

在这里插入图片描述

1.3spring创建对象的生命周期

spring创建的对象什么时候创建

回答:配置文件读取加载的时候对象就创建(scope=“singleton”)

spring读取xml文件的时候,不会创建对象
在调用容器的getBean(“id”) 得到对象(scope=“prototype”)


spring创建的对象什么时候运行

回答:当使用该对象的时候就运行


spring创建的对象什么时候销毁

回答:当spring的容器关闭的时候对象销毁

!!注意

//对Spring的生命周期进行测试
@Test
public void test05(){
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
            "applicationContext.xml"
    );
    Student student = context.getBean("student", Student.class);
    student.service();
    //猜测结果,init方法应该这service方法执行前执行
    context.close();
    //这里不报错,因为student2还存在堆内存
     student2.service();
	//这里报错,因为spring容器已经销毁
    Student student1 = context.getBean("student", Student.class);
    //猜测destroy方法应该在这句话执行后结束并且service不会再执行
    student3.service();
}

二.依赖注入

1.概念

DI (dependency injection) 依赖注入

含义:就是给对象的属性设置值.

原来给对象的属性设置值: set方法给对象设置值 构造方法给对象初始化的时候设置值.

1.1set方式设置属性

注意点:

  1. set注入 ,必须要有set方法
  2. personbean.xml
    这里不写的属性为0/Null
<?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="birthday" class="java.util.Date"></bean>

    <!--创建对象-->
    <bean id="person" class="com.itheima.di.Person">
        <!--
            name : 代表的是set方法去掉set首字母变小写的值;
            value : 给该属性设置的值(基本类型或string)
            ref :  给该对象属性设置值,ref中写的是对象的id
        -->
        <property name="id" value="1" ></property>
        <property name="userName" value="志平" ></property>
        <property name="age" value="38" ></property>
        <property name="birthday" ref="birthday"></property>
    </bean>
</beans>
  1. 测试
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class PersonTest {

    /*
      1.创建对象给对象设置属性,打印的对象是有属性的,属性是在xml中设置的.
      2.执行过程中会调用set方法,打断点查看流程
      3.是否根据set方法来设置的: 修改set方法
     */
    @Test
    public void testPerson(){
        ApplicationContext context =
                new ClassPathXmlApplicationContext("personbean.xml");
        Person person = context.getBean("person", Person.class);
        System.out.println(person);
    }
}

1.2构造方式注入

  1. 前提条件类中必须有有参构造方法
  2. personbean.xml
    这里必须写全有参构造中出现的属性,不然报编译时错误
 <!--采用构造方法创建对象-->
    <bean id="person02" class="com.itheima.di.Person">
        <!--
            constructor-arg 构造方法注入
            name 代表的构造方法上的属性名称
            value 代表传递的属性值(基本+String)
            ref  注入的是引用类型
        -->
        <constructor-arg name="name" value="小龙女" ></constructor-arg>
        <constructor-arg name="id" value="2" ></constructor-arg>
        <constructor-arg name="age" value="18" ></constructor-arg>
        <constructor-arg name="birthday" ref="birthday"></constructor-arg>
    </bean>

1.3p名称空间注入和c名称空间注入

  1. P代表propertory 属性, 是set注入的简化方式 (提供set方法)

  2. C代表Constructor 构造注入的简化方式 (提供构造方法)

  3. 配置文件
    先引入
    xmlns:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c"
    这里的c -Constructor 构造注入的简化方式属性必须全写,不然报运行时错误

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       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="birthday" class="java.util.Date"></bean>
    <!--使用p名称空间注入属性-->
    <bean id="person_p" class="com.itheima.di.Person" p:id="3" p:userName="杨过" p:age="22" p:birthday-ref="birthday"/>

    <!--使用c名称空间注入-->
    <bean id="person_c" class="com.itheima.di.Person" c:id="3" c:name="雕" c:age="220" c:birthday-ref="birthday"/>

</beans>

科普

①编译错误一般指语法错误或者很明显的逻辑错误。
如:缺少分号,少写括号,关键字书写错误等, 在eclipse往往会画红线。
②运行错误是在没有编译错误的基础上运行后产生的逻辑错误。
如:空指针异常,除数为0,越界访问等,一般会抛出异常。

1.4复杂数据类型注入

类中属性Aarry 数组 List 集合 Map集合 Set集合 Properties集合属性设置值.

  1. ComplexBean

import java.util.*;

/**
 * 采用的是set方式注入
 */
public class ComplexBean {
    private String[] arr;
    private List<Person> list;
    private Set<String> set;
    private Map<String,Person> map;
    private Properties properties;

    public String[] getArr() {
        return arr;
    }

    public void setArr(String[] arr) {
        this.arr = arr;
    }

    public List<Person> getList() {
        return list;
    }

    public void setList(List<Person> list) {
        this.list = list;
    }

    public Set<String> getSet() {
        return set;
    }

    public void setSet(Set<String> set) {
        this.set = set;
    }

    public Map<String, Person> getMap() {
        return map;
    }

    public void setMap(Map<String, Person> map) {
        this.map = map;
    }

    public Properties getProperties() {
        return properties;
    }

    public void setProperties(Properties properties) {
        this.properties = properties;
    }

    @Override
    public String toString() {
        return "ComplexBean{" +
                "arr=" + Arrays.toString(arr) +
                ", list=" + list +
                ", set=" + set +
                ", map=" + map +
                ", properties=" + properties +
                '}';
    }
}
  1. 配置文件
<!--注入复杂数据类型-->
    <bean id="complexBean" class="com.itheima.di.ComplexBean">
        <!--1.先注入数组-->
        <property name="arr">
            <array>
                <value>柯镇恶</value>
                <value>郭靖</value>
                <value>杨过</value>
            </array>
        </property>
        <!--2.注入list类型-->
        <property name="list">
            <list>
               <ref bean="person" />
                <ref bean="person02" />
                <ref bean="person_p" />
            </list>
        </property>

        <!--3.注入set集合-->
        <property name="set">
            <set>
                <value>乔峰</value>
                <value>段誉</value>
                <value>虚竹</value>
            </set>
        </property>

        <!--4.注入map-->
        <property name="map">
            <map>
                <entry key="志平" value-ref="person"/>
                <entry key="小龙女" value-ref="person02"/>
                <entry key="杨过" value-ref="person_p"/>
            </map>
        </property>

        <!--5.注入properties-->
        <property name="properties">
            <props>
                <prop key="no1">石破天</prop>
                <prop key="no2">虚竹</prop>
                <prop key="no3">张无忌</prop>
            </props>
        </property>
    </bean>
  1. 测试
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.*;

public class ComplexBeanTest {

    @Test
    public void testComplexBean(){
        ApplicationContext context =
                new ClassPathXmlApplicationContext("personbean.xml");
        ComplexBean complexBean = context.getBean("complexBean", ComplexBean.class);
        String[] arr = complexBean.getArr();
        System.out.println(Arrays.toString(arr));
        System.out.println("---------------------");
        List<Person> list = complexBean.getList();
        for (Person person : list) {
            System.out.println(person);
        }

        System.out.println("---------------------");
        Set<String> set = complexBean.getSet();
        System.out.println(set);
        System.out.println("---------------------");

        Map<String, Person> map = complexBean.getMap();
        Set<Map.Entry<String, Person>> entrySet = map.entrySet();
        for (Map.Entry<String, Person> entry : entrySet) {
            System.out.println(entry.getKey()+ " "+ entry.getValue());
        }
        System.out.println("---------------------");
        Properties properties = complexBean.getProperties();
        System.out.println(properties);

    }
}

三.注解方式的IOC和DI

1.使用注解方式创建对象

1.需要导入一个aop.jar的jar ,该包已经被spring-context.jar依赖引入了.不需要再导入(Idea)

2.在配置文件中需要进行一个包扫描的配置

2.代码实现

  1. annotationbean.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:component-scan base-package="com.sen.annotation" ></context:component-scan>
</beans>
  1. UserService接口
public interface UserService {

    //查询用户
    public void  findUsers();
}
  1. UserServiceImpl
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

//@Component注解 ===>  <bean id="userServiceImpl" class="xxxx">

// @Component    默认的id是类名首字母小写
//@Component("abc")  //手动的指定了  <bean id="abc" class="xxxx">

/**
 * 和Component注解作用一样的还有其他3个:
 * 这4个注解的作用一样
 */

//@Component   //不确定是那一层使用Component
//@Controller  //确定是表现层/控制层 使用Controller
@Service     //如果是业务逻辑使用 Service
//@Repository  // 如果是dao持久层   Repository
public class UserServiceImpl implements UserService {

    public void findUsers() {
        System.out.println("用户查询完毕");
    }
}

2.使用注解方式注入

  1. UserDao接口
public interface UserDao {

    public void  queryUsers();
}
  1. UserDaoImpl

@Repository("son1")
public class UserDaoImpl implements UserDao {
    public void queryUsers() {
        System.out.println("1111   dao的查询user方法");
    }
}
  1. UserDaoImpl02
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

//@Component注解 ===>  <bean id="userServiceImpl" class="xxxx">

// @Component    默认的id是类名首字母小写
//@Component("abc")  //手动的指定了  <bean id="abc" class="xxxx">

/**
 * 和Component注解作用一样的还有其他3个:
 * 这4个注解的作用一样
 */

//@Component   //不确定是那一层使用Component
//@Controller  //确定是表现层/控制层 使用Controller
@Service     //如果是业务逻辑使用 Service
//@Repository  // 如果是dao持久层   Repository
public class UserServiceImpl implements UserService {

    //使用自动注入的注解,将userDao的实现类UserDaoImpl注入进来
    //byType按照类型注入 ,问题如果UserDao中有多个实现类,注入的是哪个? 会报错
    @Autowired
    @Qualifier("son2")  //根据的bean id值来指定
    private UserDao userDao;

    public void findUsers() {
        System.out.println("Service用户查询完毕");
        //创建dao的对象并调用dao的query方法
        userDao.queryUsers();
    }
}
  1. 测试
public class UserServiceTest {
    @Test
    public void testUserService(){
        ApplicationContext context =
                new ClassPathXmlApplicationContext("annotationbean.xml");
        UserServiceImpl userServiceImpl = context.getBean("userServiceImpl", UserServiceImpl.class);
        userServiceImpl.findUsers();

    }
}

3.其他的注入方式

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.annotation.Resources;


@Service     //如果是业务逻辑使用 Service
public class UserServiceImpl implements UserService {

    //方式2注入:
    //@Value("#{son1}")  //将UserDaoImpl02注入进来
    //private UserDao userDao;

    @Value("志平")
    private String name;

    //注入方式3:jdk的注入
   @Resource(name="son1")
    private UserDao userDao;

    public void findUsers() {
        System.out.println("Service用户查询完毕" +name);
        //创建dao的对象并调用dao的query方法
        userDao.queryUsers();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值