SpringIOC的注解应用方式

 更新时间:2024年11月01日 15:36:25   作者:EkuinoxPrime  
在Spring框架中,除了通过xml配置文件进行Bean管理外,还可以采用注解的方式实现Bean的注册和自动装配,通过在类上添加@Component、@Service、@Repository、@Controller等注解,可以将Bean注册到IOC容器中

​ 在之前的项目中,我们都是通过xml文件进行bean或者某些属性的赋值,其实还有另外一种注解的方式,在企业开发中使用的很多,在bean上添加注解,可以快速的将bean注册到ioc容器。

1、使用注解的方式注册bean到IOC容器中

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: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">

    <!--
    使用注解需要如下步骤:
    1、添加上述四个注解中的任意一个
    2、添加自动扫描注解的组件,此操作需要依赖context命名空间
    3、添加自动扫描的标签context:component-scan

	注意:当使用注解注册组件和使用配置文件注册组件是一样的,但是要注意:
		1、组件的id默认就是组件的类名首字符小写,如果非要改名字的话,直接在注解中添加即可
		2、组件默认情况下都是单例的,如果需要配置多例模式的话,可以在注解下添加@Scope注解
    -->
    <!--
    定义自动扫描的基础包:
    base-package:指定扫描的基础包,spring在启动的时候会将基础包及子包下所有加了注解的类都自动
                扫描进IOC容器
    -->
    <context:component-scan base-package="com.example"></context:component-scan>
</beans>

PersonController.java

package com.example.controller;

import org.springframework.stereotype.Controller;

@Controller
public class PersonController {
    public PersonController() {
        System.out.println("创建对象");
    }
}

PersonService.java

package com.exxample.service;

import org.springframework.stereotype.Service;

@Service
public class PersonService {
}

PersonDao.java

package com.example.dao;

import org.springframework.stereotype.Repository;

@Repository("personDao")
@Scope(value="prototype")//默认singleton,改为prototype
public class PersonDao {
}

如果想要将自定义的bean对象添加到IOC容器中,需要在类上添加某些注解

Spring中包含4个主要的组件添加注解:

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

注意:我们虽然人为的给不同的层添加不同的注解,但是在spring看来,可以在任意层添加任意注解,但spring底层是不会给具体的层次验证注解,这样写的目的只是为了提高可读性,最偷懒的方式就是给所有想交由IOC容器管理的bean对象添加component注解

2、定义扫描包时要包含的类和不要包含的类

​ 当定义好基础的扫描包后,在某些情况下可能要有选择性的配置是否要注册bean到IOC容器中,此时可以通过如下的方式进行配置。

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: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.example" use-default-filters="false">
        <!--
        当定义好基础扫描的包之后,可以排除包中的某些类,使用如下的方式:
        type:表示指定过滤的规则
            annotation:按照注解进行排除,标注了指定注解的组件不要,expression表示要过滤的注解
            assignable:指定排除某个具体的类,按照类排除,expression表示不注册的具体类名
            aspectj:aop使用的aspectj表达式,一般不用
            custom:定义一个typeFilter,自己写代码决定哪些类被过滤掉,一般不用
            regex:使用正则表达式过滤,一般不用
        -->
<!--        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>-->

        <!--指定只扫描哪些组件,默认情况下是全部扫描的,所以此时要配置的话需要在component-scan标签中添加 use-default-filters="false"-->
        <context:include-filter type="assignable" expression="com.example.service.PersonService"/>
    </context:component-scan>
</beans>

3、使用@AutoWired进行自动注入

​ 使用注解的方式实现自动注入需要使用@AutoWired注解。

PersonController.java

package com.example.controller;

import com.example.service.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller
public class PersonController {

    @Autowired
    private PersonService personService;

    public PersonController() {
        System.out.println("创建对象");
    }

    public void getPerson(){
        personService.getPerson();
    }
}

PersonService.java

package com.example.service;

import com.example.dao.PersonDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class PersonService {

    @Autowired
    private PersonDao personDao;

    public void getPerson(){
        personDao.getPerson();
    }
}

PersonDao.java

package com.example.dao;

        import org.springframework.stereotype.Repository;

@Repository
public class PersonDao {

    public void getPerson(){
        System.out.println("PersonDao:getPerson");
    }
}

注意:当使用AutoWired注解的时候,自动装配的时候是根据类型实现的。

​ 1、如果只找到一个,则直接进行赋值,

​ 2、如果没有找到,则直接抛出异常,

​ 3、如果找到多个,那么会按照变量名作为id继续匹配,

  • 匹配上直接进行装配
  • 如果匹配不上则直接报异常

PersonServiceExt.java

package com.example.service;

import com.example.dao.PersonDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class PersonServiceExt extends PersonService{

    @Autowired
    private PersonDao personDao;

    public void getPerson(){
        System.out.println("PersonServiceExt......");
        personDao.getPerson();
    }
}

PersonController.java

package com.example.controller;

import com.example.service.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller
public class PersonController {

    @Autowired
    private PersonService personServiceExt;

    public PersonController() {
        System.out.println("创建对象");
    }

    public void getPerson(){
        personServiceExt.getPerson();
    }
}

​ 还可以使用@Qualifier注解来指定id的名称,让spring不要使用变量名,当使用@Qualifier注解的时候也会有两种情况:

​ 1、找到,则直接装配

​ 2、找不到,就会报错

PersonController.java

package com.example.controller;

import com.example.service.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;

@Controller
public class PersonController {

    @Autowired
    @Qualifier("personService")
    private PersonService personServiceExt2;

    public PersonController() {
        System.out.println("创建对象");
    }

    public void getPerson(){
        personServiceExt2.getPerson();
    }
}

​ 通过上述的代码我们能够发现,使用@AutoWired肯定是能够装配上的,如果装配不上就会报错。

4、@AutoWired可以进行定义在方法上

​ 当我们查看@AutoWired注解的源码的时候发现,此注解不仅可以使用在成员变量上,也可以使用在方法上。

PersonController.java

package com.example.controller;

import com.example.dao.PersonDao;
import com.example.service.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;

@Controller
public class PersonController {

    @Qualifier("personService")
    @Autowired
    private PersonService personServiceExt2;

    public PersonController() {
        System.out.println("创建对象");
    }

    public void getPerson(){
        System.out.println("personController..."+personServiceExt2);
//        personServiceExt2.getPerson();
    }

     /**
     * 当方法上有@AutoWired注解时:
     *  1、此方法在bean创建的时候会自动调用
     *  2、这个方法的每一个参数都会自动注入值
     * @param personDao
     */
    @Autowired
    public void test(PersonDao personDao){
        System.out.println("此方法被调用:"+personDao);
    }
    
    /**
     * @Qualifier注解也可以作用在属性上,用来被当作id去匹配容器中的对象,如果没有
     * 此注解,那么直接按照类型进行匹配
     * @param personService
     */
    @Autowired
    public void test2(@Qualifier("personServiceExt") PersonService personService){
        System.out.println("此方法被调用:"+personService);
    }
}

5、自动装配的注解@AutoWired,@Resource

​ 在使用自动装配的时候,出了可以使用@AutoWired注解之外,还可以使用@Resource注解。

​ 1、@AutoWired:是spring中提供的注解,@Resource:是jdk中定义的注解,依靠的是java的标准

​ 2、@AutoWired默认是按照类型进行装配,默认情况下要求依赖的对象必须存在,@Resource默认是按照名字进行匹配的,同时可以指定name属性。

​ 3、@AutoWired只适合spring框架,而@Resource扩展性更好

PersonController.java

package com.example.controller;

import com.example.dao.PersonDao;
import com.example.service.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;

import javax.annotation.Resource;

@Controller
public class PersonController {

    @Qualifier("personService")
    @Resource
    private PersonService personServiceExt2;

    public PersonController() {
        System.out.println("创建对象");
    }

    public void getPerson(){
        System.out.println("personController..."+personServiceExt2);
        personServiceExt2.getPerson();
    }

    /**
     * 当方法上有@AutoWired注解时:
     *  1、此方法在bean创建的时候会自动调用
     *  2、这个方法的每一个参数都会自动注入值
     * @param personDao
     */
    @Autowired
    public void test(PersonDao personDao){
        System.out.println("此方法被调用:"+personDao);
    }

    /**
     * @Qualifier注解也可以作用在属性上,用来被当作id去匹配容器中的对象,如果没有
     * 此注解,那么直接按照类型进行匹配
     * @param personService
     */
    @Autowired
    public void test2(@Qualifier("personServiceExt") PersonService personService){
        System.out.println("此方法被调用:"+personService);
    }
}

6、泛型依赖注入

​ 为了了解泛型依赖注入,首先我们需要先写一个基本的案例:

Student.java

package com.example.bean;

public class Student {
}

Teacher.java

package com.example.bean;

public class Teacher {
}

BaseDao.java

package com.example.dao;

import org.springframework.stereotype.Repository;

@Repository
public abstract class BaseDao<T> {

    public abstract void save();
}

StudentDao.java

package com.example.dao;

import com.example.bean.Student;
import org.springframework.stereotype.Repository;

@Repository
public class StudentDao extends BaseDao<Student>{
    public void save() {
        System.out.println("保存学生");
    }
}

TeacherDao.java

package com.example.dao;

import com.example.bean.Teacher;
import org.springframework.stereotype.Repository;

@Repository
public class TeacherDao extends BaseDao<Teacher> {
    public void save() {
        System.out.println("保存老师");
    }
}

StudentService.java

package com.example.service;

import com.example.dao.StudentDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class StudentService {

    @Autowired
    private StudentDao studentDao;

    public void save(){
        studentDao.save();
    }
}

TeacherService.java

package com.example.service;

import com.example.dao.TeacherDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class TeacherService {
    @Autowired
    private TeacherDao teacherDao;

    public void save(){
        teacherDao.save();
    }
}

MyTest.java

import com.example.service.StudentService;
import com.example.service.TeacherService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import javax.sql.DataSource;
import java.sql.SQLException;

public class MyTest {
    public static void main(String[] args) throws SQLException {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        StudentService studentService = context.getBean("studentService",StudentService.class);
        studentService.save();

        TeacherService teacherService = context.getBean("teacherService",TeacherService.class);
        teacherService.save();
    }
}

​ 上述代码可以完成对应的功能,但是Service层的代码能够改写成:

BaseService.java

package com.example.service;

import com.example.dao.BaseDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

public class BaseService<T> {
    
    @Autowired
    BaseDao<T> baseDao;
    
    public void save(){
        System.out.println("自动注入的对象:"+baseDao);
        baseDao.save();
    }
}

StudentService.java

package com.example.service;

import com.example.bean.Student;
import com.example.dao.StudentDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class StudentService extends BaseService<Student> {

}

TeacherService.java

package com.example.service;

import com.example.bean.Teacher;
import com.example.dao.TeacherDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class TeacherService extends BaseService<Teacher>{

}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 解决Spring Cloud Gateway获取body内容,不影响GET请求的操作

    解决Spring Cloud Gateway获取body内容,不影响GET请求的操作

    这篇文章主要介绍了解决Spring Cloud Gateway获取body内容,不影响GET请求的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • Java中ArrayList实现原理及基本方法

    Java中ArrayList实现原理及基本方法

    这篇文章主要介绍了Java中ArrayList实现原理及基本方法,ArrayList是开发中非常常用的数据存储容器之一,其底层是数组实现的,我们可以在集合中存储任意类型的数据,ArrayList是线程不安全的,擅长随机访问元素,插入和删除较慢,需要的朋友可以参考下
    2023-08-08
  • Spring Cloud整合XXL-Job的示例代码

    Spring Cloud整合XXL-Job的示例代码

    这篇文章主要介绍了springcloud整合xxl-job的示例代码,主要分为四个过程,本文给大家介绍的非常详细,需要的朋友可以参考下
    2023-05-05
  • RocketMQ中的消息发送与消费详解

    RocketMQ中的消息发送与消费详解

    这篇文章主要介绍了RocketMQ中的消息发送与消费详解,RocketMQ是一款高性能、高可靠性的分布式消息中间件,消费者是RocketMQ中的重要组成部分,消费者负责从消息队列中获取消息并进行处理,需要的朋友可以参考下
    2023-10-10
  • Java中双向链表详解及实例

    Java中双向链表详解及实例

    这篇文章主要介绍了Java中双向链表详解及实例的相关资料,需要的朋友可以参考下
    2017-04-04
  • java开发环境的完整搭建过程

    java开发环境的完整搭建过程

    这篇文章主要给大家介绍了关于java开发环境的完整搭建过程,文中介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-02-02
  • java 将jsonarray 转化为对应键值的jsonobject方法

    java 将jsonarray 转化为对应键值的jsonobject方法

    下面小编就为大家分享一篇java 将jsonarray 转化为对应键值的jsonobject方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-03-03
  • 举例分析Python中设计模式之外观模式的运用

    举例分析Python中设计模式之外观模式的运用

    这篇文章主要介绍了Python中设计模式之外观模式的运用,外观模式主张以分多模块进行代码管理而减少耦合,需要的朋友可以参考下
    2016-03-03
  • 利用Java读取二进制文件实例详解

    利用Java读取二进制文件实例详解

    这篇文章主要给大家介绍了利用Java读取二进制文件的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者使用java具有一定的参考学习价值,需要的朋友们下面跟着小编来一起学习学习吧。
    2017-08-08
  • javaweb学习总结——使用JDBC处理MySQL大数据

    javaweb学习总结——使用JDBC处理MySQL大数据

    本篇文章主要介绍了JDBC处理MySQL大数据,有时是需要用程序把大文本或二进制数据直接保存到数据库中进行储存的,非常具有实用价值,需要的朋友可以参考下。
    2016-11-11

最新评论