11Spring IoC注解式开发(上)(元注解/声明Bean的注解/注解的使用/负责实例化Bean的注解)

注解的存在主要是为了简化XML的配置。Spring6倡导全注解开发。
注解开发的优点:提高开发效率
注解开发的缺点:在一定程度上违背了OCP原则,使用注解的开发的前提是需求比较固定,变动较小。

1 注解的注解称为元注解

自定义一个注解:

package com.sunsplanter.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(value = {ElementType.TYPE,ElementType.FIELD})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface Component {
    String value();
}
  • 该注解上面修饰的注解包括:Target注解和Retention注解,这两个注解被称为元注解。
  • Target注解用来设置Component注解可以出现的位置,以上代表表示Component注解只能用在类和接口上。
  • Retention注解用来设置Component注解的保持性策略.
    SOURCE:注解只被保留在Java源文件中,class文件不包含注解.
    CLASS:注解最终被保留到class文件中,但不能被反射机制读取.
    RUNTIME:注解最终被保留到class文件中,并且可以被反射机制读取.

String value(); 是Component注解中的一个属性。该属性类型String,属性名是value。

2 管中窥豹注解的作用-通过反射机制读取注解

目标:只知道报包名:com.sunsplanter.bean,至于这个包下有多少个Bean我们不知道。哪些Bean上有注解,都不知道.
通过程序全自动化判断: 若Bean类上有Component注解时,则实例化Bean对象,如果没有,则不实例化对象。

我们准备两个Bean,一个上面有注解,一个上面没有注解。

package com.sunsplanter.bean;

import com.sunsplanter.annotation.Component;

@Component("userBean")
public class User {
}
package com.sunsplanter.bean;

public class Vip {
}
package com.sunsplanter.test;

import com.sunsplanter.annotation.Component;

import java.io.File;
import java.net.URL;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

public class Test {
    public static void main(String[] args) throws Exception {
        // 存放Bean的Map集合。key存储beanId。value存储Bean。
        Map<String,Object> beanMap = new HashMap<>();

        String packageName = "com.sunsplanter.bean";
        //将com.sunsplanter.bean转化成com/sunsplanter/bean并存到path中
        String path = packageName.replaceAll("\\.", "/");
        //获取这个包在系统中的绝对路径:file:/D:/study/spring6/spring6-005-Annotation/target/classes/com/sunsplanter/bean
        URL url = ClassLoader.getSystemClassLoader().getResource(path);
        //获取一个绝对路径下的所有子文件,并写入文件数组
        File file = new File(url.getPath());
        File[] files = file.listFiles();
        Arrays.stream(files).forEach(f -> {
        //获取两个类的相对包路径,如com.sunspalnter.bean.User...
            String className = packageName + "." + f.getName().split("\\.")[0];
            try {
                Class<?> clazz = Class.forName(className);
                if (clazz.isAnnotationPresent(Component.class)) {
                    Component component = clazz.getAnnotation(Component.class);
                    String beanId = component.value();
                    Object bean = clazz.newInstance();
                    beanMap.put(beanId, bean);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        });

        System.out.println(beanMap);
    }
}

3 声明Bean的注解

通过注解声明该类是一个bean类,今后就会被自动创建bean对象.

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

  • @Component
  • @Controller
  • @Service
  • @Repository

通过源码可以看到,@Controller、@Service、@Repository这三个注解都是@Component注解的别名。
也就是说:这四个注解的功能都一样, 只是为了增强程序的可读性,建议:

● 控制器类上使用:Controller(主要用于给前端返回数据的以及接收前端的数据的)
● service类上使用:Service(处理数据用的)
● dao类上使用:Repository
他们都是只有一个value属性。value属性用来指定bean的id,也就是bean的名字。
在这里插入图片描述

4 Spring注解的使用

如果使用以上的注解, 就不必再每一个类都使用一个bean标签管理. 如何使用以上的注解呢?
● 第一步:加入aop的依赖
● 第二步:在配置文件中添加context命名空间
● 第三步:在配置文件中指定扫描的包
● 第四步:在Bean类上使用注解

第一步:加入aop的依赖
当加入spring-context依赖之后,会关联加入aop的依赖。所以这一步不用做。

第二步:在配置文件中添加context命名空间, 分别是xmlns:context和xsi:schemeLocation

<?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">
</beans>

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

<?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.sunsplanter.bean"/>
</beans>

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

package com.sunsplanter.bean;

import org.springframework.stereotype.Component;

@Component(value = "userBean")
public class User {
}

第四步要小心, 存在两个两个Component
在这里插入图片描述
第二个时上面学习时自己建的,一定要选第一个.

第五步:编写测试程序

package com.sunsplanter.test;

import com.sunsplanter.bean.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AnnotationTest {
    @Test
    public void testBean(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        User userBean = applicationContext.getBean("userBean", User.class);
        System.out.println(userBean);
    }
}

成功输出一个对象.

如果注解的属性名是value,那么value是可以省略的。
例如:

package com.sunsplanter.bean;

import org.springframework.stereotype.Component;

@Component("userBean")
public class User {
}
package com.sunsplanter.test;

import com.sunsplanter.bean.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AnnotationTest {
    @Test
    public void testBean(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        User userBean = applicationContext.getBean("userBean", User.class);
        System.out.println(userBean);
    }
}

仍能输出一个User对象.

甚至: 如果把value属性彻底去掉,该类在被创建成bean时会被自动指定一个bean id(名字), 默认名字的规律是:Bean类名首字母小写即可。

多个包需要扫描的情况
办法1(常用): 指定需要扫描的多个包的共同父包,扫描这个共同父包. 缺点是如果父包有不需要扫描的包,则会牺牲一些效率.
办法2: 逗号分隔多个需要扫描的包:

    <context:component-scan base-package="com.sunsplanter.bean,com.sunsplanter.dao"/>

5 根据注解类型选择性实例化Bean

假设在某个包下有很多Bean,有的Bean上标注了Component,有的标注了Controller,有的标注了Service,有的标注了Repository.
目标: 现在由于某种特殊业务的需要,只允许其中所有的Controller参与Bean管理,其他的都不实例化。

这里为了方便,将这几个类都定义到同一个java源文件中了:

package com.sunsplanter.spring6.bean3;

import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

@Component
public class Selective_Instantiation_of_Objects{
    public Selective_Instantiation_of_Objects() {
        System.out.println("A的无参数构造方法执行");
    }
}

@Controller
class B {
    public B() {
        System.out.println("B的无参数构造方法执行");
    }
}

@Service
class C {
    public C() {
        System.out.println("C的无参数构造方法执行");
    }
}

@Repository
class D {
    public D() {
        System.out.println("D的无参数构造方法执行");
    }
}

@Controller
class E {
    public E() {
        System.out.println("E的无参数构造方法执行");
    }
}
<?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="true" 表示:使用spring默认的规则,只要有Component、Controller、Service、Repository中的任意一个注解标注,则进行实例化。
use-default-filters="false" 表示:不再spring默认实例化规则,即使有Component、Controller、Service、Repository这些注解标注,也不再实例化。
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> 表示只有Controller进行实例化。-->
    <context:component-scan base-package="com.sunsplanter.bean" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
    
</beans>

测试程序:

@Test
public void testChoose(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-choose.xml");
}

输出注解为@Controller的B,E构造方法执行.

目标: 现在由于某种特殊业务的需要,除了@Controller外的所有注解都参与Bean管理,仅Controller实例化。

<!--
use-default-filters="true" 表示:使用spring默认的规则,只要有Component、Controller、Service、Repository中的任意一个注解标注,则进行实例化。(不写默认是true)
use-default-filters="false" 表示:不再spring默认实例化规则,即使有Component、Controller、Service、Repository这些注解标注,也不再实例化。
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> 表示将Controller排除出实例化的范围。-->
    <context:component-scan base-package="com.sunsplanter.bean">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

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

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

相关文章

说说微信小程序的登录流程?

面试官&#xff1a;说说微信小程序的登录流程&#xff1f; 一、背景 传统的web开发实现登陆功能&#xff0c;一般的做法是输入账号密码、或者输入手机号及短信验证码进行登录 服务端校验用户信息通过之后&#xff0c;下发一个代表登录态的 token 给客户端&#xff0c;以便进行…

抖店怎么筛选达人?团队实操,百用不厌!

我是电商珠珠 在抖店入驻之后&#xff0c;品也选好了&#xff0c;就卡到了选达人这方面。 要么选的达人带不起来自己的品&#xff0c;要么就是被达人骗样品&#xff0c;要么就是没有达人愿意搭理自己。 我做抖店也已经三年时间了&#xff0c;这种情况遇到过很多&#xff0c;…

python爬虫实战(9)--获取澎pai热榜

1. 需要的类包 import pandas as pd import requests2. 请求地址 通过分析&#xff0c;数据可以直接从接口获取&#xff0c;无需解析页面标签&#xff0c;直接取出我们需要的数据即可。 def fetch_hot_news(api_url):response requests.get(api_url)if response.status_cod…

高级路由学习试题

文章目录 高级路由学习试题一.高级路由题目答案 二.OSPF 相关答案 三.基础知识答案 高级路由学习试题 一.高级路由题目 1.以下属于ITOIP特性的有&#xff08;&#xff09; A、智能 B、开放 C、融合 D、标准 2.层级化网络模型将网络划分为&#xff08;&#xff09; A、汇…

SpringMVC工作原理

文章目录 Spring MVC 概述组件介绍Spring MVC的工作原理 Spring MVC 概述 SpringMVC是一个基于MVC模式的Web框架&#xff0c;它是Spring Framework的一部分。SpringMVC主要用于在Java Web应用程序中实现Web层&#xff0c;提供了一套与平台无关的、可重用的Web组件。 Spring MV…

虚拟商城与社交购物:Facebook的新零售策略

随着数字科技的迅猛发展&#xff0c;虚拟商城和社交购物逐渐成为零售业的重要趋势。在这一潮流中&#xff0c;Facebook作为全球最大社交媒体平台之一&#xff0c;积极拥抱新零售&#xff0c;推动了虚拟商城和社交购物的融合。本文将深入探讨Facebook的新零售策略&#xff0c;以…

如何创建自己的小程序?零编程一键创建实战指南

当今瞬息万变的数字世界中&#xff0c;拥有一个属于自己的小程序已成为企业与个人展示、服务和互动的重要途径。无需编码知识&#xff0c;通过便捷的云端可视化平台&#xff0c;也可以轻松创建一款符合自身需求且功能丰富的小程序。下面给大家分享如何创建自己的小程序。 1、选…

【uview2.0】Keyboard 键盘 与 CodeInput 验证码输入 结合使用 uview

https://www.uviewui.com/components/codeInput.html &#xff08;CodeInput 验证码输入&#xff09; https://www.uviewui.com/components/keyboard.html &#xff08;Keyboard 键盘&#xff09; <u-keyboard mode"number" :dotDisabled"true" :show&q…

【活动系列】视频生成前沿研究与应用

写在前面 在视频生成即将迎来技术和应用大爆发之际&#xff0c;为了帮助企业和广大从业者掌握技术前沿&#xff0c;把握时代机遇&#xff0c;机器之心AI论坛就将国内的视频生成技术力量齐聚一堂&#xff0c;共同分享国内顶尖力量的技术突破和应用实践。 基本信息 论坛名称&…

创意天堂:25个聚焦艺术、设计和创意的网站推荐

1、即时设计 说到即时设计&#xff0c;每个人都应该熟悉它。不久前&#xff0c;即时设计开启了世界上第一个可以使用人工智能完成UI设计草案的即时设计「即时AI」大规模的内部测试也给产品设计行业带来了新的发展方向。事实上&#xff0c;对于产品设计师来说&#xff0c;即时设…

C语言中的指针变量p,特殊表达式p[0] ,(*p)[0],(px+3)[2] ,(*px)[3]化简方法

一.已知以下代码&#xff0c;请问以下 式子p[0] &#xff0c;p[1] &#xff0c;(*p)[0] &#xff0c;(*p)[1] 是什么意思&#xff1f; int A[3] {1,2,3}; int (*p)[3] &A; 因为前面的嵌入式C语言基础的章节中说过&#xff0c;数组下标其实就是数组首元素的地址往上偏…

网络服务DHCP与DNS

一 DHCP的工作原理&#xff08;租约过程&#xff09; 分类 1&#xff09;自动分配&#xff1a;分配到一个IP地址后永久使用 &#xff08;2&#xff09;手动分配&#xff1a;由DHCP服务器管理员指定IP&#xff08;打印机、报销系统&#xff09;把mac地址和ip地址做一个一一对…

Leetcode 1049 最后一块石头的重量II

题意理解&#xff1a; 有一堆石头&#xff0c;用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。 每一回合&#xff0c;从中选出任意两块石头&#xff0c;然后将它们一起粉碎。假设石头的重量分别为 x 和 y&#xff0c;且 x < y。 思路转化&#xff1a;我们可…

JAVA销售数据决策管理系统源码

JAVA销售数据决策管理系统源码 基于BS&#xff08;Extjs Strus2springhibernate Mysql&#xff09;的销售数据的决策支持 主要的功能有 系统功能具体内容包括基础资料、进货管理、出货管理、库存管理、决策分析、系统管理。

Flink-CEP 实战教程

文章目录 1. 基本概念1.1 CEP 是什么1.2 模式&#xff08;Pattern&#xff09;1.3 应用场景 2. 快速上手2.1 引入依赖2.2 入门实例 3. 模式API&#xff08;Pattern API&#xff09;3.1 个体模式3.1.1 基本形式3.1.2 量词&#xff08;Quantifiers &#xff09;3.1.3 条件&#x…

当心这46个重要漏洞!微软发布1月补丁日安全通告

近日&#xff0c;亚信安全CERT监测到微软1月补丁日发布了针对48个漏洞的修复补丁&#xff0c;其中&#xff0c;2个漏洞被评为紧急&#xff0c;46个漏洞被评为重要&#xff0c;共包含10个权限提升漏洞&#xff0c;11个远程代码执行漏洞&#xff0c;3个欺骗漏洞&#xff0c;11个信…

HTML---JavaScript操作DOM对象

目录 文章目录 本章目标 一.DOM对象概念 二.节点访问方法 常用方法&#xff1a; 层次关系访问节点 三.节点信息 四.节点的操作方法 操作节点的属性 创建节点 删除替换节点 五.节点操作样式 style属性 class-name属性 六.获取元素位置 总结 本章目标 了解DOM的分类和节点间的…

[C#]winform使用纯opencvsharp部署yolox-onnx模型

【官方框架地址】 https://github.com/Megvii-BaseDetection/YOLOX 【算法介绍】 YOLOX是一个高性能的目标检测算法&#xff0c;它是基于YOLO&#xff08;You Only Look Once&#xff09;系列算法的Anchor Free版本。YOLOX由Megvii Technology的研究团队开发&#xff0c;并在…

打架识别摄像机

随着社会治安问题的增加&#xff0c;打架事件在公共场所频繁发生&#xff0c;给社会治安带来了一定程度的威胁。因此&#xff0c;为了提高公共场所的安全性&#xff0c;可以利用现代科技&#xff0c;如人工智能和摄像技术&#xff0c;开发一种打架识别摄像机。 这种摄像机可以通…

AIGC实战——改进循环神经网络

AIGC实战——改进循环神经网络 0. 前言1. 堆叠循环网络2. 门控制循环单元3. 双向单元相关链接 0. 前言 我们已经学习了如何训练长短期记忆网络 (Long Short-Term Memory Network, LSTM) 模型&#xff0c;以学习使用给定风格生成文本&#xff0c;接下来&#xff0c;我们将学习如…