ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Spring IOC配置与使用

2021-12-07 22:31:46  阅读:138  来源: 互联网

标签:Spring 配置 bean 标签 属性 IOC public 注入


前言

​ 上篇文章简单介绍了IOC, 本文则是重点讲述如何使用Spring5里的IOC进行Bean管理, 有两种方式, 分别是基于xml文件和注解, 我们都会一一讲到。

BeanFactory接口

IOC容器的底层就是对象工厂

Spring提供了IOC容器的两种实现方式(两个接口):

  • BeanFactory: IOC容器基本实现, 是Spring内部使用的接口, 不提供给开发人员使用, 加载文件的时候不会船舰对象, 在获取对象的时候才会创建对象

  • ApplicationContext: BeanFactory接口的子接口, 提供更多更强大的功能, 加载配置文件的时候就会把在配置文件中配置好的对象进行创建

    ApplicationContext的四个常用实现类:

    • **FileSystemXmlApplicationContext:**加载配置文件的时候采用的是项目的路径, 也就是绝对路径。
    • **ClassPathXmlApplicationContext:**加载配置文件的时候根据ClassPath位置, 也就是项目相对路径。
    • **XmlWebApplicationContext:**在Web环境下初始化监听器的时候会加载该类。
    • **AnnotationConfigApplicationContext:**根据注解的方式启动Spring 容器。

SpringDI的方式

​ Spring提供了三种方式来依赖注入,有构造方法注入, setter方法注入以及接口注入。其中Spring以往推荐使用Setter的方法现在改成推荐构造方法注入。使用构造方法注入需要注意的一点就是要避免循环依赖。所谓的循环依赖指的就是在A对象的构造方法中Spring要注入B,而在B对象中Spring要注入A。这个时候会形成一个闭环因为Spring不知道该先注入哪一个接着会抛出异常。而Spring建议的处理方式是说如果遇到这种情况的话就改用Setter方式注入。

Bean管理(基于xml)

基于xml创建对象:

  • 在Spring配置文件中, 使用bean标签创建对象
  • 在bean标签中有多个属性, 常用的有:
    • id: 唯一标识, 用于获取对象
    • class: 类的全路径
  • 创建对象的时候, 默认的是执行无参构造方法完成对象创建
<!--配置User对象的创建-->
<bean id="user" class="com.ayu.User"></bean>

基于xml方式注入属性:

  • 使用set方法进行注入

    在bean标签内使用property标签完成属性注入:

    name: 类中属性名称

    value: 属性中注入的值

    <!--使用set方法进行参数注入-->
    <bean id="user1" class="com.ayu.User">
    	<property name="name" value="Tom"></property>
    	<property name="age" value="11"></property>
    </bean>
    
  • 使用有参构造器进行注入

    在bean标签内使用constructor-arg标签完成属性注入:

    name: 类中属性名称

    value: 属性中注入的值

    <!--使用有参构造方法进行参数注入-->
    <bean id="user2" class="com.ayu.User">
    	<constructor-arg name="name" value="Jerry"></constructor-arg>
    	<constructor-arg name="age" value="11"></constructor-arg>
    </bean>
    

xml注入其他属性:

  • 字面量

    • null值

      使用标签

      <!--null值-->
      <property name="name">
          <null/>
      </property>
      
    • 属性值包含特殊符号

      使用CDATA

      <!--特殊字符-->
      <property name="name">
          <value>
          	<![CDATA[<<时生>>]]>
          </value>
      </property>
      
  • 注入外部bean

    使用ref属性注入外部创建好的bean对象

    <!--外部bean-->
    <bean id="userService" class="com.ayu.service.UserService">
            <property name="userDao" ref="userDao"></property>
    </bean>
    
    <bean id="userDao" class="com.ayu.dao.UserDao"></bean>
    
  • 注入内部bean

    直接在property标签里创建bean标签

    <!--内部bean-->
    <bean id="emp" class="com.ayu.bean.Emp">
        <property name="name" value="张三"></property>
        <property name="dept">
            <bean id="dept" class="com.ayu.bean.Dept">
                <property name="deptNo" value="101"></property>
            </bean>
        </property>
    </bean>
    
  • 级联赋值

    对属性里的bean对象的属性进行赋值操作

    <!--级联赋值-->
    <bean id="emp1" class="com.ayu.bean.Emp">
        <property name="name" value="张三"></property>
        <property name="dept" ref="dept1"></property>
        <property name="dept.deptNo" value="102"></property>
    </bean>
    <bean id="dept1" class="com.ayu.bean.Dept"></bean>
    

xml注入集合属性:

  • array标签对数组进行赋值
  • list标签对List集合进行赋值
  • set标签对Set集合进行赋值
  • map标签对Map集合进行赋值
<bean id="stu" class="com.ayu.collection.Student">
<property name="courses">
    <array>
        <value>语文</value>
        <value>数学</value>
        <value>英语</value>
    </array>
</property>
<property name="list">
    <list>
        <value>java</value>
        <value>go</value>
        <value>c++</value>
    </list>
</property>
<property name="map">
    <map>
        <entry key="java" value="88"></entry>
        <entry key="c++" value="78"></entry>
    </map>
</property>
<property name="set">
    <set>
        <value>MySQL</value>
        <value>SQLServer</value>
    </set>
</property>
<property name="courseList">
    <list>
        <ref bean="course1"></ref>
        <ref bean="course2"></ref>
    </list>
</property>
</bean>

<bean id="course1" class="com.ayu.collection.Course">
	<property name="name" value="Spring5"></property>
</bean>
<bean id="course2" class="com.ayu.collection.Course">
	<property name="name" value="SpringMVC"></property>
</bean>

使用util标签共享bean:

<!-- 配置命名空间 -->
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans 
                    http://www.springframework.org/schema/beans/spring-beans.xsd
                    http://www.springframework.org/schema/util
                    http://www.springframework.org/schema/util/spring-util-2.0.xsd">

<!-- 使用util标签来配置共享的bean-->
<util:list id="bookList">
    <value>大话数据结构</value>
    <value>程序是怎样跑起来的</value>
    <value>操作系统导论</value>
</util:list>

<bean id="book" class="com.ayu.collection.Book">
    <property name="list" ref="bookList"></property>
</bean>

使用p命名空间配置bean:

<!-- 配置命名空间 -->
xmlns:p="http://www.springframework.org/schema/p"

<!--使用p命名空间来配置bean-->
<bean id="user" class="com.ayu.User" p:name="Tom" p:age="11"></bean>

Bean作用域:

Spring中可以使用scope属性来配置bean的作用域:

  • singleton: 单例, 在初始化配置文件时生成单例bean对象**(默认)**
  • prototype: 原型的, 在初始化配置文件时不生成bean对象, 使用时返回不同的bean对象
  • request: web环境下每一个request请求都会返回一个不同的bean, 只在本次请求中有效
  • session: web环境下每一个request请求都会返回一个不同的bean, 在session中有效
<!--设置scope属性-->
<bean id="user" class="com.ayu.User" scope="singleton"></bean>

Bean生命周期:

  1. 通过构造方法生成bean的实例
  2. 为bean注入属性
  3. 调用初始化方法**(通过init-method属性配置)**
  4. bean的使用
  5. IOC容器关闭时,调用销毁方法**(通过destroy-method属性配置)**

创建一个测试用的Order类:

public class Order {
    private String name;
    
    public Order() {
        System.out.println("1.无参构造");
    }
    
    public void setName(String name) {
        this.name = name;
        System.out.println("2.set方法");
    }
    
    public void initMethod() {
        System.out.println("3.初始化方法");
    }

    public void destroyMethod() {
        System.out.println("5.销毁方法");
    }
    
    @Test
    public void testOrder() {
        ApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml");
        Order order = context.getBean("order", Order.class);
        System.out.println("4.获取到bean对象");
        System.out.println(order);
        ((ClassPathXmlApplicationContext) context).close();
    }
}

配置文件:

<bean id="order" class="com.ayu.bean.Order" init-method="initMethod" destroy-method="destroyMethod">
    <property name="name" value="手机"></property>
</bean>

测试结果:

1.无参构造
2.set方法
3.初始化方法
4.获取到bean对象
com.ayu.bean.Order@69b0fd6f
5.销毁方法

Bean的后置处理器:

使用后置处理器后的生命周期:

  1. 通过构造方法生成bean的实例
  2. 为bean注入属性
  3. 将bean传给后置处理器的postProcessBeforeInitialization方法
  4. 调用初始化方法**(通过init-method属性配置)**
  5. 将bean传给后置处理器的postProcessAfterInitialization方法
  6. bean的使用
  7. IOC容器关闭时,调用销毁方法**(通过destroy-method属性配置)**

创建一个后置处理器类实现BeanPostProcessor接口:

public class MyBeanPost implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("初始化之前");
        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("初始化之后");
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
}

在配置文件中配置BeanPostProcessor:

<bean id="myBeanPost" class="com.ayu.bean.MyBeanPost"></bean>

测试结果:

1.无参构造
2.set方法
初始化之前
3.初始化方法
初始化之后
4.获取到bean对象
com.ayu.bean.Order@66d1af89
5.销毁方法

Bean的自动装配

bean标签的autowire属性实现自动装配, autowire有两个常用的值:

  • byName: 根据属性名称注入, 注入值bean的id值和类属性值名称需一样

    <bean id="emp" class="com.ayu.autowrite.Emp" autowire="byName">
        <!--<property name="dept" ref="dept"></property>-->
    </bean>
    <bean id="dept" class="com.ayu.autowrite.Dept"></bean>
    
  • byType: 根据属性类型注入

    <bean id="emp" class="com.ayu.autowrite.Emp" autowire="byType">
        <!--<property name="dept" ref="dept"></property>-->
    </bean>
    <bean id="dept" class="com.ayu.autowrite.Dept"></bean>
    

    注: 通过byType自动装配,已配置的bean中有多个该类型的bean时会报错

Bean管理(基于注解)

Spring针对bean管理提供的注解

下面四个注解功能是一样的,都可以用来创建 bean 实例

  • @Controller: 控制器, 推荐给controller层添加此注解。
  • @Service: 业务逻辑, 推荐给业务逻辑层添加此注解。
  • @Repository: 仓库管理, 推荐给数据访问层添加此注解。
  • @Component: 给不属于以上基层的组件添加此注解。

基于注解实现对象创建

  1. 开启组件扫描:

    如果扫面多个包, 可以用逗号隔开, 或是扫描包的上层目录

    <context:component-scan base-package="com.ayu"></context:component-scan>
    
  2. 创建类, 在类上添加对象注解

    //value属性可以不写, 会默认类名首字母小写为value的值
    @Repository(value="userDao")
    public class UserDaoImpl implements UserDao{
        @Override
        public void hello() {
            System.out.println("hello dao");
        }
    }
    

开启组件扫描细节配置

<!--示例一:use-default-filters表示现在不使用默认filter,自己配置filter
	content:include-filter 设置扫面那些内容-->
<content:component-scan base-package="com.ayu" use-default-filters="false">
    <content:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</content:component-scan>
<!--示例二:下面配置扫面包所有内容
	content:exclude-filter 设置哪些内容不进行扫描-->
<content:component-scan base-package="com.ayu" use-default-filters="false">
    <content:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</content:component-scan>

基于注解实现属性注入

  • @Autowired: 根据属性类型进行自动装配

    @Service
    public class UserService {
    
        //不需要set方法
        @Autowired
        private UserDao userDaO;
    
        public void hello() {
            System.out.println("hello service");
            userDaO.hello();
        }
    }
    
  • @Qualifier: 根据属性名称进行注入, 通常和@Autowired一起使用

    @Service
    public class UserService {
    
        //不需要set方法
        //区别同一接口下多个实现类
        @Autowired
        @Qualifier(value="userDaoImpl")
        private UserDao userDaO;
    
        public void hello() {
            System.out.println("hello service");
            userDaO.hello();
        }
    }
    
  • @Resource: 可以根据类型注入,也可以根据名称注入(这个注解是JDK提供的)

    @Resource(value="userDaoImpl")
    private UserDao userDaO;
    
  • @Value: 注入普通类型属性

    @Value(value = "service")
    private String name;
    

完全注解开发

创建配置类, 代替xml配置文件

@Configuration
@ComponentScan(basePackages = {"com.ayu"})
public class SpringConfig {}

此时应使用AnnotationConfigApplicationContext这个实现类:

//AnnotationConfigApplicationContext需要将配置类传给它
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
UserService userService = context.getBean("userService", UserService.class);
userService.hello();

最后

我的个人主页: www.ayu.link
本文连接: ┏ (゜ω゜)=☞

标签:Spring,配置,bean,标签,属性,IOC,public,注入
来源: https://blog.csdn.net/Y_Ace/article/details/121780151

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有