[SSM]Spring IoC注解式开发

news2025/2/27 14:59:21

目录

十二、Spring IoC注解式开发

12.1回顾注解

12.1.1自定义注解

12.1.2使用注解

12.1.3通过反射机制读取注解

12.2声明Bean的注解

12.3Spring注解的使用

12.4选择性实例化Bean

12.5负责注入的注解

12.5.1@Value

12.5.2@Autowired与@Qualifier

12.5.3@Resource

12.6全注解式开发


十二、Spring IoC注解式开发

12.1回顾注解

  • 注解的存在主要是为了简化XML的配置,Spring6倡导全注解开发。

12.1.1自定义注解

package com.hhb.annotation;
​
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
​
/**
 * 自定义注解
 */
//标注注解的注解叫做元注解。@Target注解用来修饰@Component可以出现的位置
//以下表示@Component注解可以出现在类上、属性上
//@Target(value = {ElementType.TYPE, ElementType.FIELD})
//以下表示@Component注解可以出现在类上
//@Target(value = {ElementType.TYPE})
//使用注解的时候,如果注解的属性是value的话,value可以省略
//@Target({ElementType.TYPE})
//使用某个注解的时候,如果注解的属性值是数组,并且数组中只有一个元素,大括号可以省略
@Target(ElementType.TYPE)
//@Retention也是一个元注解,用来标注@Component注解最终保留在class文件当中,并且可以被反射机制读取。
@Retention(RetentionPolicy.RUNTIME)
public @interface Component {
    //定义注解的属性,String是属性类型,value是属性名
    String value();
    //数组属性,String[]是属性类型,names是属性名
    //String[] names();
}
  • 以上是自定义的一个注解:Component

  • 该注解上面修饰的注解包括:Target注解和Retention注解,这两个注解被称为元注解。

  • Target注解用来设置Component注解可以出现的位置,以上代表表示Component注解只能在类和接口上。

  • Retention注解用来设置Component注解的保持性策略,以上代表Component注解可以被反射机制读取。

12.1.2使用注解

package com.hhb.bean;
​
import com.hhb.annotation.Component;
​
//@Component(属性名=属性值,属性名=属性值,...)
//@Component(value = "userBean")
//如果属性名是value,value可以省略
@Component("userBean")
public class User {
    //编译器报错,不能出现在这里
    //@Component(value = "test")
    //private String name;
}

测试

package com.hhb.client;
​
import com.hhb.annotation.Component;
​
public class ReflectAnnotation {
    public static void main(String[] args) throws Exception{
        //通过反射机制怎么获取注解
        //获取类
        Class<?> aClass = Class.forName("com.hhb.bean.User");
        //判断类上面有没有这个注解
        if (aClass.isAnnotationPresent(Component.class)) {
            //获取类上的注解
            Component annotation = aClass.getAnnotation(Component.class);
            //访问注解属性
            System.out.println(annotation.value());
        }
    }
}

12.1.3通过反射机制读取注解

  • 当Bean类上有Component注解时,则实例化Bean对象,如果没有,则不实例化对象。

有注解的Bean

package com.hhb.bean;
​
import com.hhb.annotation.Component;
​
@Component("vipBean")
public class Vip {
}

没有注解的Bean

package com.hhb.bean;
​
public class Order {
}

反射解析注解

package com.hhb.client;
​
import com.hhb.annotation.Component;
​
import java.io.File;
import java.net.URL;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
​
public class ComponentScan {
    public static void main(String[] args) {
        Map<String, Object> beanMap = new HashMap<>();
        //目前只知道一个包的名字,扫描这个包下所有的类,当这个类上有@component注解的时候,实例化该对象,然后放到Map集合中
        String packageName = "com.hhb.bean";
        //开始写扫描程序
        //使用正则表达式,将packageName中的 . 替换成 /
        String packagePath = packageName.replaceAll("\\.", "/");
        //com是在类的根路径下的一个目录
        URL url = ClassLoader.getSystemClassLoader().getResource(packagePath);
        String path = url.getPath();
        //获取一个绝对路径下的所有文件
        File file = new File(path);
        File[] files = file.listFiles();
        Arrays.stream(files).forEach(f -> {
            try {
                String className = packageName + "." + f.getName().split("\\.")[0];
                //通过反射机制解析注解
                Class<?> aClass = Class.forName(className);
                //判断类上是否有这个注解
                if (aClass.isAnnotationPresent(Component.class)) {
                    //获取注解
                    Component annotation = aClass.getAnnotation(Component.class);
                    String id = annotation.value();
                    //创建对象
                    Object obj = aClass.newInstance();
                    beanMap.put(id,obj);
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });
        System.out.println(beanMap);
    }
}

执行结果


12.2声明Bean的注解

  • 负责声明Bean的注解,常见的包括四个:

    • @Component

    • @Controller

    • @Service

    • @Repository

  • @Controller、@Service、@Repository这三个注解都是@Component注解的别名,也就是说,这四个注解的功能都一样,用哪个都可以。

  • 为了增强程序的可读性,建议:

    • 控制器类上使用:Controller

    • service类上使用:Service

    • dao类上使用:Repository

  • 他们都是只有一个value属性,value属性用来指定bean的id,也就是bean的名字。

 

 

12.3Spring注解的使用

第一步:加入aop的依赖

 

第二步:在配置文件中添加context命名空间

<?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 htt
p://www.springframework.org/schema/beans/spring-beans.xsd
 http://www.springframework.org/schema/context ht
tp://www.springframework.org/schema/context/spring-context.xsd">
</beans>

第三步:在配置文件中指定要扫描的包

<context:component-scan base-package="com.hhb.bean"/>

第四步:在Bean类上使用注解

package com.hhb.bean;
​
import org.springframework.stereotype.Service;
​
@Service(value = "orderBean")
public class Order {
}
package com.hhb.bean;
​
import org.springframework.stereotype.Controller;
​
@Controller
public class Student {
}

测试

@Test
public void testBeanComponent() {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
    User userBean = applicationContext.getBean("userBean", User.class);
    System.out.println(userBean);
​
    Order orderBean = applicationContext.getBean("orderBean", Order.class);
    System.out.println(orderBean);
​
    Student student = applicationContext.getBean("student", Student.class);
    System.out.println(student);
​
    Vip vip = applicationContext.getBean("vip", Vip.class);
    System.out.println(vip);
}
  • 如果注解的属性名是value,那么value可以省略。

  • 如果将value属性彻底去掉,spring会被Bean自动取名,默认名字为:Bean类名首字母小写即可。

  • 如果是多个包,有两种解决方案

    • 在配置文件中指定多个包,用逗号隔开。

    • <context:component-scan base-package="com.hhb.dao,com.hhb.bean"/>
    • 指定多个包的共同父包。(会降低效率)

    • <context:component-scan base-package="com.hhb"/>

12.4选择性实例化Bean

<?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">
​
    <!--第一种解决方案:
        use-default-filters="false"
        如果这个属性是false,表示com.hhb.bean2包下所有的带有声明Bean的注解全部失效
    -->
        <context:component-scan base-package="com.hhb.bean2" use-default-filters="false">
            <!--只有@Repository被包含进来生效--> 
            <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
        </context:component-scan>
    <!--第二种解决方案:
         use-default-filters="true"
         如果这个属性的值是true,表示com.hhb.bean2下的所有的带有声明Bean的注解全部生效
         use-default-filters="true" 默认值是true,不用写
    -->
    <context:component-scan base-package="com.hhb.bean2" use-default-filters="true">
        <!--@Repository注解失效-->
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
    </context:component-scan>
​
</beans>

12.5负责注入的注解

  • @Component、@Controller、@Service、@Repository这四个注解是用来声明Bean的,声明后这些Bean将被实例化。

  • 给Bean属性赋值需要使用这些注解:

    • @Value

    • @Autowired

    • @Qualifier

    • @Resource

12.5.1@Value

  • 当属性的类型是简单类型时,可以使用@Value注解进行注入。

Product

package com.hhb.bean3;
​
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
​
@Component
public class Product {
    @Value("苹果")
    private String name;
    @Value("5")
    private int num;
​
    public void setName(String name) {
        this.name = name;
    }
​
    public void setNum(int num) {
        this.num = num;
    }
​
    @Override
    public String toString() {
        return "Product{" +
                "name='" + name + '\'' +
                ", num=" + num +
                '}';
    }
}
  • @Value注解可以直接使用在属性上,也可以使用在setter方法上,也可以使用在构造方法中。

  • 当@Value注解使用在属性上时,可以不用写setter方法。

public Product(@Value("苹果") String name, @Value("5") int num) {
    this.name = name;
    this.num = num;
}

spring-di-annotation.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.hhb.bean3"/>
​
</beans>

测试

@Test
public void testDI() {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-di-annotation.xml");
    Product product = applicationContext.getBean("product", Product.class);
    System.out.println(product);
}

12.5.2@Autowired与@Qualifier

  • @Autowired注解可以用来注入非简单类型,被翻译为:自动连线的或者自动装配的。

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

  • @Autowired可以标注在哪里?

    • 构造方法上

    • 方法上

    • 形参上

    • 注解上

    • 属性上

OrderDao接口

package org.hhb.dao;
​
public interface OrderDao {
    void insert();
}

OrderDaoForMySQL

package org.hhb.dao.impl;
​
import org.hhb.dao.OrderDao;
import org.springframework.stereotype.Repository;
​
@Repository
public class OrderDaoForMySQL implements OrderDao {
    @Override
    public void insert() {
        System.out.println("mysql~~~");
    }
}
  • 构造方法和setter方法都没有提供,在属性上使用@Autowired注解,注入成功。

  • @Autowired注解可以出现在setter方法上。

  • @Autowired注解可以出现在构造方法上。

  • @Autowired注解可以出现在构造方法的形参上。

  • 当有参数的构造方法只有一个时,@Autowired注解可以省略。

OrderService

package org.hhb.service.impl;
​
import org.hhb.dao.OrderDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
​
@Service
public class OrderService {
    @Autowired
    private OrderDao orderDao;
​
    public void setOrderDao(OrderDao orderDao) {
        this.orderDao = orderDao;
    }
​
    public void generate() {
        orderDao.insert();
    }
}
  • Autowired注解默认是byType进行注入的,也就是说根据类型注入的,如果以上程序中,OrderDao接口还有另外一个实现类,会出现问题。

  • 解决方案:@Autowired注解和@Qualifier注解联合起来才可以根据名称进行装配,在@Qualifier注解中指定Bean名称。

package org.hhb.service.impl;
​
import org.hhb.dao.OrderDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
​
@Service
public class OrderService {
    @Autowired
    @Qualifier("orderDaoForOracle")
    private OrderDao orderDao;
​
    public void setOrderDao(OrderDao orderDao) {
        this.orderDao = orderDao;
    }
​
    public void generate() {
        orderDao.insert();
    }
}

12.5.3@Resource

  • @Resource注解也可以完成非简单类型注入,它和@Autowired注解有什么区别?

    • @Resource注解是JDK扩展包中的,也就是说属于JDK的一部分。所以该注解是标注注解,更加具有通用性。

    • @Autowired注解是Spring框架自己的。

    • @Autowired注解默认根据名称装配byName,未指定name时,使用属性名作为name。通过name找不到的话会自动启动通过类型byType装配。

    • @Autowired注解默认根据类型装配byType,如果想根据名称装配,需要配合@Qualifier注解一起用。

    • @Resource注解用在属性上、setter方法上。

    • @Autowired注解用在属性上、setter方法上、构造方法上、构造方法参数上。

  • @Resource注解属于JDK扩展包,所以不在JDK当中,需要额外引入以下依赖:如果是JDK8的话不需要额外引入依赖,高于JDK11或低于JDK8需要引入以下依赖。

<dependency>
 <groupId>jakarta.annotation</groupId>
 <artifactId>jakarta.annotation-api</artifactId>
 <version>2.1.1</version>
</dependency>

UserDaoForMySQL

package org.hhb.dao.impl;
​
import org.hhb.dao.OrderDao;
import org.springframework.stereotype.Repository;
​
@Repository("orderDao")
public class OrderDaoForMySQL implements OrderDao {
​
    @Override
    public void insert() {
        System.out.println("mysql~~~");
    }
}

OrderService

package org.hhb.service.impl;
​
import jakarta.annotation.Resource;
import org.hhb.dao.OrderDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
​
@Service
public class OrderService {
    @Resource(name = "orderDao")
    private OrderDao orderDao;
​
    public void setOrderDao(OrderDao orderDao) {
        this.orderDao = orderDao;
    }
​
    public void generate() {
        orderDao.insert();
    }
}

12.6全注解式开发

  • 所谓的全注解开发就是不再使用spring配置文件了,写一个配置类来代替配置文件。

Spring6Config

package org.hhb;
​
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
​
//编写一个类,代替Spring框架的配置文件
@Configuration
@ComponentScan({"org.hhb.dao", "org.hhb.service"})
public class Spring6Config {
}

测试

@Test
public void testNoXML(){
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Spring6Config.class);
    OrderService orderService = context.getBean("orderService", OrderService.class);
    orderService.generate();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/787248.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Maven发布中央仓库始终报403

把域名 oss.sonatype.org 全部替换为&#xff1a;s01.oss.sonatype.org

Spring Cloud【SkyWalking服务环境搭建、微服务接入SkyWalking探针、Docker搭建Elasticsearch环境 】(十四)

目录 分布式请求链路追踪_SkyWalking服务环境搭建 分布式请求链路追踪_微服务接入SkyWalking探针 分布式请求链路追踪_Docker搭建Elasticsearch环境 分布式请求链路追踪_SkyWalking使用Elasticsearch持久化 分布式请求链路追踪_SkyWalking自定义链路追踪 分布式请求链路…

疲劳驾驶检测和识别3:Android实现疲劳驾驶检测和识别(含源码,可实时检测)

疲劳驾驶检测和识别3&#xff1a;Android实现疲劳驾驶检测和识别(含源码&#xff0c;可实时检测) 目录 疲劳驾驶检测和识别3&#xff1a;Android实现疲劳驾驶检测和识别(含源码&#xff0c;可实时检测) 1.疲劳驾驶检测和识别方法 2.人脸检测方法 3.疲劳驾驶检测和识别模型…

24 鼠标常用事件

鼠标进入&#xff1a;enterEvent鼠标离开&#xff1a;leaveEvent鼠标按下&#xff1a;mousePressEvent鼠标释放&#xff1a;mouseRelaseEvent鼠标移动&#xff1a;mouseMoveEvent 提升为自定义控件MyLabel 代码&#xff1a; //mylabel.h #ifndef MYLABEL_H #define MYLABEL_H#…

linux LVM磁盘管理

Linux运维过程中经常会遇到扩容的场景&#xff0c;下面做一点简单笔记&#xff0c;所谓好记性不如烂笔头。 1、新建磁盘挂载 &#xff08;1&#xff09;先看看主机上有没有挂载磁盘或挂载的磁盘有没有剩余的。 如下图可以看到这台机器挂了两个盘&#xff0c;一个/dev/sda,这…

【项目管理】第三节:PMP备考学习建议

文章目录 1.项目管理的价值观与方法论2.PMP开始的形式和题型 1.项目管理的价值观与方法论 对于中国考生而言&#xff0c;PMP”考试有两关要过:第一关是认知升级&#xff0c;考生通过学习和梳理项目管理知识&#xff0c;提升自己对项目管理的认知;第二关是思维升级&#xff0c;…

【Vue3】Vue3中的组合式API是什么?hook是什么?什么是“组合式函数”?项目中如何使用自定义 hook 函数?

组合式API与hook 一、什么是组合式 API&#xff1f;&#xff08;composition-api&#xff09;二、什么是组合式函数&#xff1f;&#xff08;hook&#xff09;2.1 无状态的函数&#xff08;utils&#xff09;2.2 有状态的函数&#xff08;hooks&#xff09;2.3 utils与hooks的联…

yolov5s模型剪枝详细过程(v6.0)

本文参考github上大神的开源剪枝项目进行学习与分享&#xff0c;具体链接放在文后&#xff0c;希望与大家多多交流&#xff01; 一、原模型训练 在官方源码上训练yolov5模型&#xff0c;支持v6.0分支的n/s/m/l模型&#xff0c;我这里使用的是v5s&#xff0c;得到后将项目clone到…

Cesium态势标绘专题-椭圆(标绘+编辑)

标绘专题介绍:态势标绘专题介绍_总要学点什么的博客-CSDN博客 入口文件:Cesium态势标绘专题-入口_总要学点什么的博客-CSDN博客 辅助文件:Cesium态势标绘专题-辅助文件_总要学点什么的博客-CSDN博客 本专题没有废话,只有代码,代码中涉及到的引入文件方法,从上面三个链…

图像处理之Hough变换检测直线

hough变换-直线检测 一、 前言二、Hough 变换三、直线检测四、代码实现1.hough检测2.画直线代码3.画hough空间代码4.检测结果 一、 前言 霍夫变换是一种特征检测(feature extraction)&#xff0c;被广泛应用在图像分析&#xff08;image analysis&#xff09;、计算机视觉(com…

[算法通关村] 1.2 链表的插入

上一节我们谈到了链表的概念&#xff0c;以及链表的创建方法&#xff0c;忘记的小伙伴可以复习一下&#xff1a; [算法通关村] 1.1 单向链表的创建 今天我们来探究一下链表的插入&#xff0c;链表的插入共有 3 种可能性&#xff0c;分别是在链表的头部插入、在中间插入&#x…

CMake学习-All in one

参考引用 CMake与Make最简单直接的区别通过例子学习CMakeLIO-SAM 1. 引言 1.1 什么是 CMake 1.1.1 CMake 背景 1.1.2 CMake 定义 CMake 是一个跨平台的安装&#xff08;编译&#xff09;工具&#xff0c;可以用简单的语句来描述所有平台的安装&#xff08;编译&#xff09;过…

基础算法-数组模拟队列

队列&#xff1a;先进先出 什么叫做队列&#xff1a; 就是一个特殊的数组。这个数组&#xff0c;最前面叫队头&#xff0c;最后面叫队尾。只允许在最后面添加元素&#xff0c;只允许在最前面删除元素。 解题思路&#xff1a; 用一个数组 q 保存数据。 用 hh 代表队头&…

关于PyTorch中一维卷积Conv1d的理解

首先明确一点&#xff0c;PyTorch中的一维卷积是从左往右做的&#xff0c;不是从上往下。 然后明确第二点&#xff0c;一维卷积和二维卷积最大的区别在于&#xff0c;一维卷积的卷积方向只有一个维度&#xff0c;一维卷积的卷积核不像二维卷积核一样可以左右和上下两个维度移动…

Mysql-主从复制与读写分离

Mysql 主从复制、读写分离 一、前言&#xff1a;二、主从复制原理1.MySQL的复制类型2. MySQL主从复制的工作过程;3.MySQL主从复制延迟4. MySQL 有几种同步方式&#xff1a;5.Mysql应用场景 三、主从复制实验1.主从服务器时间同步1.1 master服务器配置1.2 两台SLAVE服务器配置 2…

CRM系统化整合从N-1做减法实践 | 京东物流技术团队

1 背景 京销易系统已经接入大网、KA以及云仓三个条线商机&#xff0c;每个条线商机规则差异比较大&#xff0c;当前现状是独立实现三套系统分别做支撑。 2 目标 2022年下半年CRM目标是完成9个新条线业务接入&#xff0c;完成销售过程线上化&#xff0c;实现销售规则统一。 …

【Git】—— 分⽀的基本操作

目录 &#xff08;一&#xff09;理解分⽀ &#xff08;二&#xff09;创建分⽀ &#xff08;三&#xff09;切换分⽀ &#xff08;四&#xff09;合并分⽀ &#xff08;五&#xff09;删除分⽀ 总结 &#xff08;一&#xff09;理解分⽀ 本章开始介绍 Git 的杀⼿级功能之…

结构型设计模式:装饰器模式

设计模式专栏目录 创建型设计模式-单例模式/工厂模式/抽象工厂 行为型设计模式&#xff1a;模板设计模式/观察者设计模式/策略设计模式 结构型设计模式&#xff1a;装饰器模式 C#反射机制实现开闭原则的简单工厂模式 目录 设计模式专栏目录设计模式分类设计模式的设计原则装饰…

Java体系总览

一、基础篇 JVM JVM内存结构 堆、栈、方法区、直接内存、堆和栈区别 Java内存模型 内存可见性、重排序、顺序一致性、volatile、锁、final 垃圾回收 内存分配策略、垃圾收集器&#xff08;G1&#xff09;、GC算法、GC参数、对象存活的判定 JVM参数及调优 Java对象模型 …

windows环境下docker数据迁移到其他盘

docker安装在C盘&#xff0c;使用一段时间后&#xff0c;C盘爆满。因此想把C盘中的数据迁移到其他盘&#xff0c;以释放C盘空间。分为以下步骤&#xff1a; 1、启动docker软件&#xff0c;打开PowerShell并切换到Docker Compose配置文件的目录。 Docker Compose配置文件的目录…