Spring IoC注解

news2025/2/27 15:15:26

一、回顾反射机制

反射的调用三步:1)获取类。2)获取方法。3)调用方法

调用方法:调用哪个对象,哪个方法,传什么参数,返回什么值。

方法(Do)类:

package test1;
public class Do {
    //定义方法
    public void doSome(){
        System.out.println("doSome()方法执行");
    }
    public String doSome(String s){
        System.out.println("doSome(String s)方法执行");
        return s;
    }
    public String doSome(String s,int i){
        System.out.println("doSome(String s,int i)方法执行");
        return s+i;
    }
}

测试类:

public class test1 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        //先获取类
       Class clazz=Class.forName("test1.Do");
       //再获取方法
       Method m= clazz.getDeclaredMethod("doSome", String.class, int.class);
       //调用方法
        //四要素:调用哪个对象,哪个方法,传什么参数,返回什么值
        //创建对象
       Object obj= clazz.newInstance();
       Object value= m.invoke(obj,"张三",23);
       System.out.println(value);
    }
    }

SpringDI核心实现

一个小练习:为手写Spring框架打前提

有这么一个类,类名叫:test1.Student,这个类符合javabean构造,还知道这个类中有一个属性叫age,且age类型为int类型,使用反射机制调用set方法,给Student对象的age属性赋值。

一个完整的javabean的Student类:

package test1;
public class Student {
    private String name;
    private int age;
    public Student(){

    }
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

 测试类:

public class test1 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        //有这么一个类,类名叫:test1.Student
        //这个类符合javabean构造
        //还知道这个类中有一个属性叫age,且age类型为int类型
        //使用反射机制调用set方法,给Student对象的age属性赋值
        String className="test1.Student";//类名
        String propertyName="age";//属性
        //获取类
        Class clazz=Class.forName(className);
        //获取方法名
        String name="set"+propertyName.toUpperCase().charAt(0)+propertyName.substring(1);
        //获取方法
       Method m=clazz.getDeclaredMethod(name,int.class);
       //创建对象
       Object obj=clazz.newInstance();
       //调用方法
        m.invoke(obj,23);//无返回值类型
        System.out.println(obj);

    }
    }

org:框架的开发人员

com:框架的使用者

二、Spring IoC注解式开发

1.注解

2.反射注解

先创建一个注解,并定义其属性:

package com.hei;
import javax.lang.model.element.Element;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//注解
@Target(ElementType.TYPE)//用于描述类、接口的注解
@Retention(RetentionPolicy.RUNTIME)//利用保留在class文件中,也可以用反射机制
public @interface Component {
    //注解属性
    //String属性类型
    //value属性名
    String value();
}

 创建一个类,将注解附上:

package com.hei;
//value可以省略
@Component(value = "userbean")
public class User {

}

主函数利用反射机制:

现获取注解所在的类,再判断这个类上是否有注解,若存在,则获取注解。

public class test {
    public static void main(String[] args) throws ClassNotFoundException {
        //利用反射机制获取注解属性
        //现获取注解所在类
        Class clazz=Class.forName("com.hei.User");
        //判断类上有没有这个注解
       if(clazz.isAnnotationPresent(Component.class)){
           //获取注解
           Component com= (Component) clazz.getAnnotation(Component.class);
           System.out.println(com.value());
       }
    }
}

3.组件扫描原理

是扫描包下的类是否带了注解

  类加载器

Java类加载器(Class Loader)是Java虚拟机(JVM)的一部分,负责将类的字节码加载到内存中,并将其转换为可执行的Java对象。根据类的全限定名(包括包路径和类名),定位并读取类文件的字节码。

public class ClassLoaderExample {
    public static void main(String[] args) throws ClassNotFoundException {
        // 使用系统类加载器加载并实例化一个类
        ClassLoader classLoader = ClassLoader.getSystemClassLoader();
        Class<?> clazz = classLoader.loadClass("com.example.MyClass");
        MyClass myObject = (MyClass) clazz.newInstance();
        
        // 调用加载的类的方法
        myObject.sayHello();
    }
}
class MyClass {
    public void sayHello() {
        System.out.println("Hello, World!");
    }
}

输出了:Hello,world. 

题目

给一个包,将包下带有注解的类,扫描出来。

先创建一个注解,并定义其属性:

package com.hei.Annotion;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//注解
@Target(ElementType.TYPE)//用于描述类、接口的注解
@Retention(RetentionPolicy.RUNTIME)//利用保留在class文件中,也可以用反射机制
public @interface Component {
    //注解属性
    //String属性类型
    //value属性名
    String value();
}

创建带有注解的类和不带有注解的类:

package com.hei.bean;
import com.hei.Annotion.Component;
@Component("userbean")
public class User {

}

package com.hei.bean;
public class Vip {
}

package com.hei.bean;
import com.hei.Annotion.Component;
@Component("oderbean")
public class Order {
}

测试类:

package com.hei.client;
import com.hei.Annotion.Component;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

public class test {
    public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {
        Map<String,Object> hm=new HashMap<>();
        //只知道包名,要扫描包下的带有注释的类
        String Package="com.hei.bean";//包名
        //要把这个包名替换成路径
        String Pacpath=Package.replaceAll("\\.","/");
        //System.out.println(Pacpath);
        //运用类加载器,获取路径
       URL url= ClassLoader.getSystemClassLoader().getResources(Pacpath).nextElement();
       //获取绝对路径
        String path=url.getPath();
        //获取绝对路径下的文件
        File file=new File(path);
        File[] files=file.listFiles();//获取路径下所有内容
        for(File f:files){
            String name=f.getName();
            String s = name.split("\\.")[0];
            //System.out.println(s);
            String ClassName=Package+"."+s;//获取文件所在位置包名加类名
            //利用反射机制,获取包名
            Class clazz=Class.forName(ClassName);
            if(clazz.isAnnotationPresent(Component.class)){
               Component com= (Component) clazz.getAnnotation(Component.class);
               String id= com.value();
               Object obj= clazz.newInstance();
                hm.put(id,obj);
            }
        }
        System.out.println(hm);
    }
}

4.声明Bean的注解 

后面三个注解都是基于第一个注解。

5.Spring注解使用

第一步:加入依赖在引入spring-context依赖中就已包含。

配置文件(spring.xml):

<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">
<!--    给spring框架指定要扫描哪些包的类-->
    <context:component-scan base-package="com.hei.bean"/>
</beans>

扫描的类:

package com.hei.bean;
import org.springframework.stereotype.Component;
@Component("userbean")
public class User {
}

package com.hei.bean;
import org.springframework.stereotype.Service;
@Service("vipbean")
public class Vip {
}

package com.hei.bean;
import org.springframework.stereotype.Controller;
@Controller//将value全部省略,bean名为类名变小写
public class Order {
}

测试类:

package com.hei;
import com.hei.bean.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
    @org.junit.Test
    public void test(){
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring.xml");
        User u= applicationContext.getBean("userbean",User.class);
        System.out.println(u);
        Vip v= applicationContext.getBean("vipbean",Vip.class);
        System.out.println(v);
        Order o=applicationContext.getBean("order",Order.class);
        System.out.println(o);
    }
    }

若有多个包:

6.选择性实例化Bean

第一种实现方法:

先定义带有注解的类:

package com.hei.bean;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

@Controller
public class A {
    public A(){
        System.out.println("A的无参构造执行");
    }
}
@Component
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的无参构造执行");
    }
}

 spring.xml配置文件中,use-deafult-filters=false使全部注解失效,通过context:include-filter type使想要的注解生效。

<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">
<!--    给spring框架指定要扫描哪些包的类-->
    <context:component-scan base-package="com.hei.bean" use-default-filters="false">
       <context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
    </context:component-scan>
     
</beans>

测试类:

public class Test {
    @org.junit.Test
    public void test(){
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring.xml");
    }
    }

第二种方法:

通过context:exclude-filter type=" "使的注解失效。

 <context:component-scan base-package="com.hei.bean" >
      <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

7.负责注入的注解

1) @value注解

当属性类型为简单类型时,可以使用@Value注解进行注入,@Value可以用在定义属性上,也可用在set方法上,也可以用在构造方法的形参上。

Student类:

package com.hei.bean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class Student {
    @Value("张三")
    private String name;
    @Value("25")
    private int age;

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

spring.xml:

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

测试类:

public class Test {
    @org.junit.Test
    public void test(){
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring.xml");
        Student s=applicationContext.getBean("student",Student.class);
        System.out.println(s);
    }
    }

2)@Autowired

@Autowired注解使用的时候,不需要指定任何属性,直接使用即可。

@Autowired可以用在定义属性上,也可用在set方法上,也可以用在构造方法的形参上。

@Autowiredhe@Qualifier联合使用,可根据名字自动装配。

接口:

package com.hei.bean;
public interface Order {
     void insert();
}

连接接口的类:

import com.hei.bean.Order;
import org.springframework.stereotype.Repository;

@Repository("orderDao")
public class OrderDao implements Order {
    @Override
    public void insert() {
        System.out.println("数据库正在保存信息");
    }
}

调用方法的类:

package com.hei.bean.Service;
import com.hei.bean.Dao.OrderDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service("orderService")
public class OrderService {
    @Autowired
    private OrderDao orderDao;
    public void save(){
        orderDao.insert();
    }
}

spring.xml:

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

 测试类:

public class Test {
    @org.junit.Test
    public void test() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        OrderService o= applicationContext.getBean("orderService", OrderService.class);
        o.save();
    }
    }

3)@Resource

引入resource依赖:

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

 接口:

package com.hei.bean;
public interface Order {
     void insert();
}

连接接口的类:

package com.hei.bean.Dao;
import com.hei.bean.Order;
import org.springframework.stereotype.Repository;

@Repository("orderDao")
public class OrderDao implements Order {
    @Override
    public void insert() {
        System.out.println("数据库正在保存信息");
    }
}

调用方法的类:

package com.hei.bean.Service;
import com.hei.bean.Dao.OrderDao;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

@Service("orderService")
public class OrderService {
    @Resource(name = "orderDao")
    private OrderDao orderDao;
    public void save(){
        orderDao.insert();
    }
}

spring.xml:

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

测试类:

public class Test {
    @org.junit.Test
    public void test() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        OrderService o= applicationContext.getBean("orderService", OrderService.class);
        o.save();

    }
    }

8.全注解式开发

全注解式开发:不再使用配置文件,而是编写一个类替代配置文件。

其他的接口、类和上面的例子一样。

SpringConfig类:

package com.hei.bean;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
//编写一个类代替Spring框架的配置文件
@Configuration
@ComponentScan({"com.hei.bean.Dao","com.hei.bean.Service"})
public class SpringConfig {
}

测试类:

public class Test {
    @org.junit.Test
    public void T(){
        AnnotationConfigApplicationContext a=new AnnotationConfigApplicationContext(SpringConfig.class);
        OrderService o= a.getBean("orderService",OrderService.class);
        o.save();
    }
}

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

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

相关文章

eFuse电子保险丝,需要了解的技术干货来啦

热保险丝作为一种基本的电路保护器件&#xff0c;已经成功使用了150多年。热保险丝有效可靠、易用&#xff0c;具有各种不同的数值和版本&#xff0c;能够满足不同的设计目标。然而&#xff0c;对于寻求以极快的速度切断电流的设计人员来说&#xff0c;热保险丝不可避免的缺点就…

【高校科研前沿】北京大学赵鹏军教授团队在Nature Communications发文:揭示城市人群移动的空间方向性

文章简介 论文名称&#xff1a;Unravelling the spatial directionality of urban mobility 第一作者及单位&#xff1a;赵鹏军&#xff08;教授|第一作者|北京大学&#xff09;&王浩&#xff08;博士生|共同一作|北京大学&#xff09;; 通讯作者及单位&#xff1a;赵鹏军…

SCI二区|鲸鱼优化算法(WOA)原理及实现【附完整Matlab代码】

目录 1.背景2.算法原理2.1算法思想 3.结果展示4.参考文献5.代码获取 1.背景 2016年&#xff0c;S Mirjalili受到自然界座头鲸社会行为启发&#xff0c;提出了鲸鱼优化算法&#xff08;Whale Optimization Algorithm, WOA&#xff09;。 2.算法原理 WOA模拟了座头鲸的社会行为…

会议室占用全透明化,内幕大揭秘!

会议室管理的现实问题 &#x1f3e2; 有限的会议室资源: 在现代办公环境中&#xff0c;会议室资源通常是有限的&#xff0c;特别是在大型企业或繁忙的办公楼内&#xff0c;会议室的预订和管理变得尤为重要。 &#x1f552; 复杂的预订流程: 常常会出现会议室预订流程繁琐、不…

2024年6月14日 十二生肖 今日运势

小运播报&#xff1a;2024年6月14日&#xff0c;星期五&#xff0c;农历五月初九 &#xff08;甲辰年庚午月己酉日&#xff09;&#xff0c;法定工作日。今天世界献血日&#xff0c;捐献新鲜血液&#xff0c;挽救更多生命&#xff0c;每位献血者都是英雄&#xff01; 红榜生肖…

【论文复现|智能算法改进】基于改进鲸鱼优化算法的移动机器人多目标点路径规划

目录 1.算法原理2.数学模型3.改进点4.结果展示5.参考文献6.代码获取 1.算法原理 SCI二区|鲸鱼优化算法&#xff08;WOA&#xff09;原理及实现【附完整Matlab代码】 2.数学模型 使用 A* 算法生成所有目标点之间的距离矩阵U: U [ d 1 − 1 d 1 − 2 d 1 − 3 ⋯ d 1 − i d…

【JVM】JVisualVM的介绍、使用和GC过程

VisualVM介绍 VisualVM 是Netbeans的profile子项目&#xff0c;已在JDK6.0 update 7 中自带&#xff0c;能够监控线程&#xff0c;内存情况&#xff0c;查看方法的CPU时间和内存中的对 象&#xff0c;已被GC的对象&#xff0c;反向查看分配的堆栈(如100个String对象分别由哪几…

C#——类和对象详情

类和对象 类 类是一种数据结构&#xff0c;它可以包含数据成员&#xff08;常量和字段&#xff09;、函数成员&#xff08;方法、属性、事件、索引器、运算符、实例构造函数、静态构造函数和析构函数&#xff09;以及嵌套类型。类类型支持继承&#xff0c;继承是一种机制&…

【第9章】“基础工作流”怎么用?(图生图/局部重绘/VAE/更多基础工作流)ComfyUI基础入门教程

🎁引言 学到这里,大家是不是会比较纠结,好像还在持续学习新的东西,未来还有多少基础的东西要学习,才能正常使用ComfyUI呢? 这其实需要转变一个心态。 AI绘画还处于一个快速迭代的过程,隔三岔五的就会有很多新技术、新模型出现,ComfyUI目前同样处于一个快速更新的阶…

Flask基础2-Jinja2模板

目录 1.介绍 2.模板传参 1.变量传参 2.表达式 3.控制语句 4.过滤器 5.自定义过滤器 6.测试器 7.块和继承 flask基础1 1.介绍 Jinja2:是Python的Web项目中被广泛应用的模板引擎,是由Python实现的模板语言,Jinja2 的作者也是 Flask 的作 者。他的设计思想来源于Django的模…

弃用Docker Desktop:在WSL2中玩转Docker之Docker Engine 部署与WSL入门

Docker技术概论 在WSL2中玩转Docker之Docker Engine部署 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://bl…

安装操作系统1-Win10版本介绍及硬件要求

注意&#xff1a;安装系统&#xff0c;首先弄清有哪些版本及所需硬件环境。 1.Win10有哪些版本 微软将 Win10为以下7个版本&#xff1a; Windows 10 家庭版&#xff08;Home&#xff09; 面向所有普通用户&#xff0c;提供Win 10的基本功能。此版本适合个人家庭用户使用&am…

Typora 破解、激活!亲测有效!2024 最新激活方法

Typora 破解、激活&#xff01;亲测有效&#xff01;2024 最新激活方法 Typora是一款简单易用的Markdown编辑器。 Markdown是一种可以使用普通文本编辑器编写的标记语言&#xff0c;通过简单的标记语法&#xff0c;它可以使普通文本内容具有一定的格式&#xff0c;其目标是实现…

机器学习第四十三周周报 aGNN

文章目录 week43 aGNN摘要Abstract1. 题目2. Abstract3. 网络架构3.1 aGNN3.1.1 输入与输出模块3.1.2 嵌入层3.1.3编码器解码器模块&#xff1a;带有多头注意力层的GCN 3.2 可释性模型&#xff1a;SHAP 4. 文献解读4.1 Introduction4.2 创新点4.3 实验过程4.3.1 实验区域以及场…

深度解析ONLYOFFICE协作空间2.5版本新功能

深度解析ONLYOFFICE协作空间2.5版本新功能 上个月&#xff0c;4月份&#xff0c;ONLYOFFICE协作空间推出了V2.5版本&#xff0c;丰富了一些很实用的新功能&#xff0c;之前已经有文章介绍过了&#xff1a; ONLYOFFICE 协作空间 2.5 现已发布https://blog.csdn.net/m0_6827469…

没有特斯拉的开源专利,就没有中国电动车产业今天的成就?

原文链接&#xff1a;没有特斯拉的开源专利&#xff0c;就没有中国电动车产业今天的成就&#xff1f; 特斯拉的开源专利&#xff0c;对中国电动车产业的影响有多大&#xff1f; 2014年6月12日&#xff08;June 12, 2014&#xff09;&#xff0c;特斯拉&#xff08;TESLA&…

OpenAPI Typescript Codegen 的基本使用

下载 axios npm install axios OpenAPI Typescript Codegen 官网&#xff1a;https://github.com/ferdikoomen/openapi-typescript-codegen 安装 OpenAPI Typescript Codegen npm install openapi-typescript-codegen --save-dev–input&#xff1a;指定接口文档的路径、url …

小主机折腾记26

双独立显卡调用问题 前两天将tesla p4从x99大板上拆了下来&#xff0c;将880G5twr上的rx480 4g安装到了x99大板上&#xff0c;预计是dg1输出&#xff0c;rx480做3d运算。安装完驱动后&#xff0c;还想着按照之前tesla p4的设置方法去设置rx480&#xff0c;结果果然&#xff0c…

SPI通信外设

SPI外设介绍 时钟频率就是SCK波形的频率&#xff0c;一个SCK时钟交换一个bit&#xff0c;所以时钟频率一般体现的是传输速度&#xff0c;单位是Hz或者bit/s。可以看出来&#xff0c;SPI的时钟其实就是由pclk分频得来的&#xff0c;pclk就是外设时钟&#xff0c;APB2的PCLK就是7…

Mybatis做批量操作

foreach只能处理记录数不多的批量操作&#xff0c;数据量大了后&#xff0c;先不说效率&#xff0c;能不能成功操作都是问题&#xff0c;所以这里讲一讲Mybatis正确的批量操作方法 在获取opensession对象的时候&#xff0c;我们可以传入参数&#xff0c;告诉Mybatis我要批量操…