Spring 6(二)【IOC(3)

简介: Spring 6(二)【IOC

Spring 6(二)【IOC(2)https://developer.aliyun.com/article/1532217

1.11、基于 XML 的自动装配

所谓自动装配其实就是为了减少我们配置 Spring 配置文件的工作量,比较一个 JavaBean 如果有很多属性的话,我们自己一个一个去配置添加属性太复杂了,所以就有了自动装配这个概念。

自动装配有两种方式:通过属性类型来自动装配(byType),通过属性名来自动装配(byName)。

  • byType:根据类型匹配IOC容器中的某个兼容类型的bean,为属性自动赋值
  • 如果在IOC中,没有任何一个兼容类型的bean能够为属性赋值,则该属性不装配,即值为默认值 null
  • 如果在IOC中,有多个兼容类型的bean能够为属性赋值,则抛出异常NoUniqueBeanDefinitionException
  • byName:将自动装配的属性的属性名,作为bean的id在IOC容器中匹配相对应的bean进行赋值

这里我们写一个测试模拟我们开发的一个的场景,controller 负责响应通过 service 来实现,service 会调用 dao 层来实现持久化。

(1)编写 Service 层代码:

package com.lyh.study.service;
 
public interface UserService {
    void addUser();
}
package com.lyh.study.service;
 
import com.lyh.study.dao.UserDao;
 
public class UserServiceImpl implements UserService {
 
    private UserDao userDao;
 
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
 
    @Override
    public void addUser() {
        System.out.println("addUser() 方法执行");
        userDao.addUser();
    }
}

(2)编写 Dao 层代码 :

package com.lyh.study.dao;
 
public interface UserDao {
    void addUser();
}
package com.lyh.study.dao;
 
public class UserDaoImpl implements UserDao{
 
    @Override
    public void addUser() {
        System.out.println("添加成功");
    }
}

(3)编写 controller 层代码:

package com.lyh.study.controller;
 
import com.lyh.study.service.UserService;
 
public class UserController {
 
    private UserService userService;
 
    public void setUserService(UserService userService) {
        this.userService = userService;
    }
 
    public void addUser(){
        userService.addUser();
    }
 
}

1.11.1、byType 自动装配

<bean id="userController" class="com.lyh.study.controller.UserController" autowire="byType"/>
    <bean id="userService" class="com.lyh.study.service.UserServiceImpl" autowire="byType"/>
    <bean id="userDao" class="com.lyh.study.dao.UserDaoImpl"/>

1.11.2、byName 自动装配

<bean id="userController" class="com.lyh.study.controller.UserController" autowire="byName"/>
    <bean id="userService" class="com.lyh.study.service.UserServiceImpl" autowire="byName"/>
    <bean id="userDao" class="com.lyh.study.dao.UserDaoImpl"/>

测试:

    @Test
    public void testAutoWireByType(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
        UserController userController = ac.getBean(UserController.class);
        userController.addUser();
    }

运行结果:

addUser() 方法执行
添加成功

2、基于注解管理 Bean

除了上面的直接手动配置 Spring 配置文件以外,我们实际用的更多应该就是使用注解注入了。

2.1、开启扫描组件

       Spring 默认不使用注解装配 Bean,因此我们需要在 Spring 的 XML 配置中,通过 context:component-scan 元素开启 Spring Beans的自动扫描功能。开启此功能后,Spring 会自动从扫描指定的包(base-package 属性设置)及其子包下的所有类,如果类上使用了 @Component 注解,就将该类装配到容器中。

也就是在 Spring 配置文件中加这么一行:

<context:component-scan base-package="com.lyh.study"/>

注意:在使用 context:component-scan 元素开启自动扫描功能前,首先需要在 XML 配置的一级标签  中添加 context 相关的约束。

2.1.1、默认扫描方式

<context:component-scan base-package="com.lyh.study"/>

也就是我们上面演示的,它会扫描 com.lyh.study 包下所有被 @Component 注解标注的类并帮我们注册到 IOC 容器中管理。

2.1.2、指定要排除的组件

标签

<!-- context:include-filter标签:指定在原有扫描规则的基础上追加的规则 -->
    <!-- use-default-filters属性:取值false表示关闭默认扫描规则 -->
    <context:component-scan base-package="com.lyh.study" use-default-filters="false">
        <!--
    type:设置包含的依据
    type="annotation",根据注解排除,expression中设置要排除的注解的全类名
    type="assignable",根据类型排除,expression中设置要排除的类型的全类名
      -->
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        <context:exclude-filter type="assignable" expression="com.lyh.study.controller.UserController"/>
    </context:component-scan>

2.1.3、仅扫描指定组件

标签

<!-- context:include-filter标签:指定在原有扫描规则的基础上追加的规则 -->
    <!-- use-default-filters属性:取值false表示关闭默认扫描规则 -->
    <context:component-scan base-package="com.lyh.study" 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.lyh.study.controller.UserController"/>
    </context:component-scan>

2.2、使用注解定义 Bean

Spring 提供了以下多个注解,这些注解可以直接标注在 Java 类上,将它们定义成 Spring Bean。

注解 说明
@Component 该注解用于描述 Spring 中的 Bean,它是一个泛化的概念,仅仅表示容器中的一个组件(Bean),并且可以作用在应用的任何层次,例如 Service 层、Dao 层等。 使用时只需将该注解标注在相应类上即可。
@Repository 该注解用于将数据访问层(Dao 层)的类标识为 Spring 中的 Bean,其功能与 @Component 相同。
@Service 该注解通常作用在业务层(Service 层),用于将业务层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。
@Controller 该注解通常作用在控制层(如SpringMVC 的 Controller),用于将控制层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。

2.3、@Autowired 注入

单独使用 @Autowired注解时,默认根据类型装配(byType)

2.3.1、属性注入

上面 2.1 中我们的 UserController 中有一个属性是 UserService 类型的对象,而 UserService 这个类当中也有一个类型为 UserDao 的属性;所以我们当时必须提供 setter 方法,因为它是是通过 setter 方法进行注入的;但是现在使用注解开发我们就可以省去 setter 方法:

package com.lyh.study.service;
 
import com.lyh.study.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
 
@Service
public class UserServiceImpl implements UserService {
 
    @Autowired
    private UserDao userDao;
 
    @Override
    public void addUser() {
        System.out.println("addUser() 方法执行");
        userDao.addUser();
    }
}
import org.springframework.stereotype.Repository;
 
@Repository
public class UserDaoImpl implements UserDao{
 
    @Override
    public void addUser() {
        System.out.println("添加成功");
    }
}
package com.lyh.study.controller;
 
import com.lyh.study.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
 
@Controller
public class UserController {
 
    @Autowired
    private UserService userService;
 
    public void addUser(){
        userService.addUser();
    }
 
}

这次我们使用了注解 @Service、Repository、Controller 分别标注了我们的 UserController、UserDao 和 UserController ,而且即使它们的 Bean 中包含了一些属性,我们并没有提供 setter 方法,因为使用注解开发时,不需要给 Bean 提供 setter 方法

测试:

    @Test
    public void testAutoWireByType(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
        UserController userController = ac.getBean("userController",UserController.class);
        userController.addUser();
    }

运行结果:

addUser() 方法执行
添加成功

2.3.2、set 注入

上面的属性注入中,我们把 @Autowired 这个注解标注在了属性上,这种方式不需要我们实现属性的 setter 方法;而 set 注入是直接把 @Autowired 这个注解标注在方法上:

package com.lyh.study.controller;
 
import com.lyh.study.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
 
@Controller
public class UserController {
    
    private UserService userService;
 
    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }
 
    public void addUser(){
        userService.addUser();
    }
 
}
package com.lyh.study.service;
 
import com.lyh.study.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
 
@Service
public class UserServiceImpl implements UserService {
    
    private UserDao userDao;
 
    @Autowired
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
 
    @Override
    public void addUser() {
        System.out.println("addUser() 方法执行");
        userDao.addUser();
    }
}

这里不再测试运行结果了,效果和属性注入是一样的。个人推荐这种方式,尽量养成一个给属性添加 setter 方法的好习惯,而且属性注入 Idea 会给一个警告提示,虽然也用起来没问题,但是强迫症实在受不了。

Spring 6(二)【IOC(4)https://developer.aliyun.com/article/1532221

相关文章
|
15天前
|
XML Java 数据格式
Spring5系列学习文章分享---第一篇(概述+特点+IOC原理+IOC并操作之bean的XML管理操作)
Spring5系列学习文章分享---第一篇(概述+特点+IOC原理+IOC并操作之bean的XML管理操作)
18 1
|
29天前
|
XML Java API
IoC 之 Spring 统一资源加载策略
IoC 之 Spring 统一资源加载策略
32 2
|
15天前
|
XML druid Java
Spring5系列学习文章分享---第二篇(IOC的bean管理factory+Bean作用域与生命周期+自动装配+基于注解管理+外部属性管理之druid)
Spring5系列学习文章分享---第二篇(IOC的bean管理factory+Bean作用域与生命周期+自动装配+基于注解管理+外部属性管理之druid)
22 0
|
11天前
|
XML Java 数据库连接
Spring6(二):IoC容器(2)
Spring6(二):IoC容器
17 2
|
11天前
|
XML Java 数据格式
Spring6(二):IoC容器(3)
Spring6(二):IoC容器(3)
14 1
|
11天前
|
XML Java 数据格式
Spring6(二):IoC容器(1)
Spring6(二):IoC容器(1)
21 1
|
22天前
|
存储 Java 测试技术
Java Spring IoC&DI :探索Java Spring中控制反转和依赖注入的威力,增强灵活性和可维护性
Java Spring IoC&DI :探索Java Spring中控制反转和依赖注入的威力,增强灵活性和可维护性
17 1
|
29天前
|
XML Java API
IoC 之 Spring 统一资源加载策略【Spring源码】
IoC 之 Spring 统一资源加载策略【Spring源码】
26 2
|
29天前
|
存储 Java Spring
Spring IOC 源码分析之深入理解 IOC
Spring IOC 源码分析之深入理解 IOC
39 2
|
1月前
|
XML Java 数据格式
Spring--两大核心之一--IOC
Spring--两大核心之一--IOC