[SSM]Spring IoC注解式开发

目录

十二、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();
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【数据挖掘】使用 LSTM 进行时间和序列预测

一、说明 每天&#xff0c;人类在执行诸如过马路之类的任务时都会做出被动预测&#xff0c;他们估计汽车的速度和与汽车的距离&#xff0c;或者通过猜测球的速度并相应地定位手来接球。这些技能是通过经验和实践获得的。然而&#xff0c;由于涉及众多变量&#xff0c;预测天气或…

【Linux命令200例】chown修改文件或目录的所有者

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;全栈领域新星创作者✌&#xff0c;2023年6月csdn上海赛道top4。 &#x1f3c6;本文已收录于专栏&#xff1a;Linux命令大全。 &#x1f3c6;本专栏我们会通过具体的系统的命令讲解加上鲜活的实操案例对各个命令进行深入…

iOS-持久化

目的 1.快速展示&#xff0c;提升体验 已经加载过的数据&#xff0c;用户下次查看时&#xff0c;不需要再次从网络&#xff08;磁盘&#xff09;加载&#xff0c;直接展示给用户 2.节省用户流量&#xff08;节省服务器资源&#xff09; 对于较大的资源数据进行缓存&#xf…

MonoBehaviour 组件

MonoBehaviour 组件是指继承了 MonoBehaviour 类的脚本组件&#xff0c;可以附加到游戏对象上&#xff0c;用于控制游戏对象的行为和交互。 MonoBehaviour 类是 Unity 中的一个基类&#xff0c;提供了许多方法和事件&#xff0c;用于处理输入、渲染、碰撞、协程等操作。 Unity…

vue项目启动npm run serve常见报错及解决办法

报错1&#xff1a; 如图&#xff1a; 解决方法&#xff1a;重新安装core-js , npm i core-js 报错2&#xff1a; Syntax Error: EslintPluginImportResolveError: unable to load resolver “alias”. 解决方法&#xff1a;npm install eslint-import-resolver-alias -D 报…

【数据结构和算法15】二叉树的实现

二叉树是这么一种树状结构&#xff1a;每个节点最多有两个孩子&#xff0c;左孩子和右孩子 重要的二叉树结构 完全二叉树&#xff08;complete binary tree&#xff09;是一种二叉树结构&#xff0c;除最后一层以外&#xff0c;每一层都必须填满&#xff0c;填充时要遵从先左后…

配置SQL提示

问题描述 SpringBoot工程中&#xff1a;使用Select注入的时候没有提示 例如&#xff1a; 在正常情况下&#xff1a; 在没有配置SQL提示的时候&#xff1a; 原因分析&#xff1a; 没有进行SQL配置 解决方案&#xff1a; 选中Select注入中的SQL语句&#xff0c;使用IDEA中的快…

自学网络安全(黑客)的误区

前言 网络安全入门到底是先学编程还是先学计算机基础&#xff1f;这是一个争议比较大的问题&#xff0c;有的人会建议先学编程&#xff0c;而有的人会建议先学计算机基础&#xff0c;其实这都是要学的。而且这些对学习网络安全来说非常重要。 一、网络安全学习的误区 1.不要…

Vite 4.4 正式版发布,全面拥抱 Lightning CSS

一、什么是 Vite Vite 是由 Evan You 推出的下一代前端构建工具,是官方 Vue CLI 的替代品,速度非常快。Vite 利用原生 ESM 并使用 Rollup 处理开发和打包工作。 从功能上讲,它的工作方式类似于预配置的 webpack 和 webpack-dev-server,但在速度方面具有无可比拟的优势。 …

elasticsearch报错问题

标题1.报错问题 标题2.新建一个配置类 package cn.itcast.hotel.config;import org.apache.http.HttpHost; import org.apache.http.client.config.RequestConfig; import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestClientBuilder; import o…

redis 1

shell 1&#xff1a;安装1. 源码安装&#xff08;CENTOS&#xff09; 2.999:可能会出现得问题1. 编译出错 1&#xff1a;安装 1. 源码安装&#xff08;CENTOS&#xff09; 官方下载源码包 wget https://download.redis.io/redis-stable.tar.gz # 安装依赖 yum install gcc解压…

前端学习——ajax (Day4)

同步代码和异步代码 回调函数地狱和 Promise 链式调用 回调函数地狱 Promise - 链式调用 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge&quo…

【Linux命令200例】cmp文件比较工具

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;全栈领域新星创作者✌&#xff0c;2023年6月csdn上海赛道top4。 &#x1f3c6;本文已收录于专栏&#xff1a;Linux命令大全。 &#x1f3c6;本专栏我们会通过具体的系统的命令讲解加上鲜活的实操案例对各个命令进行深入…

Tangible Software Solutions Crack

Tangible Software Solutions Crack 有形软件解决方案-最准确可靠的源代码转换器&#xff0c;在VB.NET、C#、Java、C和Python之间进行转换&#xff0c;同时节省了无数小时的艰苦工作和宝贵的时间。 主要优点&#xff1a; 节省宝贵时间 准确全面 安全-您的代码永远不会离开您的机…

HTML中的焦点管理

前言 焦点作为页面交互中的重要一环&#xff0c;涉及到的知识点也比较多&#xff0c;有必要做一个统一的总结。 HTML 中的可获取焦点的元素 具有 href 属性的 HTMLAnchorElement/HTMLAreaElement非禁用态的 HTMLInputElement/HTMLSelectElement/HTMLTextAreaElement/HTMLBut…

《零基础入门学习Python》第063讲:论一只爬虫的自我修养11:Scrapy框架之初窥门径

上一节课我们好不容易装好了 Scrapy&#xff0c;今天我们就来学习如何用好它&#xff0c;有些同学可能会有些疑惑&#xff0c;既然我们懂得了Python编写爬虫的技巧&#xff0c;那要这个所谓的爬虫框架又有什么用呢&#xff1f;其实啊&#xff0c;你懂得Python写爬虫的代码&…

RocketMQ教程-(5)-功能特性-顺序消息

顺序消息为 Apache RocketMQ 中的高级特性消息&#xff0c;本文为您介绍顺序消息的应用场景、功能原理、使用限制、使用方法和使用建议。 应用场景​ 在有序事件处理、撮合交易、数据实时增量同步等场景下&#xff0c;异构系统间需要维持强一致的状态同步&#xff0c;上游的事…

JavaWeb银行项目

主要功能 实现了贷款、存款、理财、提现、充值、开户、绑卡、转账等功能。 介绍 1、这个是一个类似有支付宝一样的web项目。 2、登录和注册&#xff0c;都是通过手机号来进行的。 3、注册的新用户需要先进行开户操作&#xff0c;然后进行绑卡操作。 4、在开户的时候回给你…

Linux 学习记录57(ARM篇)

Linux 学习记录57(ARM篇) 本文目录 Linux 学习记录57(ARM篇)一、外部中断1. 概念2. 流程图框 二、相关寄存器1. GIC CPU Interface (GICC)2. GIC distributor (GICD)3. EXTI registers 三、EXTI 寄存器1. 概述2. 内部框图3. 寄存器功能描述4. EXTI选择框图5. EXTI_EXTICR1 &…

金融中的数学:贝叶斯公式

1.贝叶斯定理 贝叶斯定理是概率论中的一项重要定理&#xff0c;用于在已知某一事件的条件下&#xff0c;求另一事件发生的概率。它是根据条件概率推导出来的&#xff0c;得名于英国数学家托马斯贝叶斯。 贝叶斯定理可以表示为&#xff1a; 这个式子就是贝叶斯公式&#xff0c…