Spring IoC注解

一、回顾反射机制

反射的调用三步: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();
    }
}

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

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

相关文章

GPT-4o更易越狱?北航南洋理工上万次测试详解!

GPT-4o&#xff0c;比上一代更容易遭受越狱攻击&#xff1f; 北航和南洋理工的研究人员通过上万次API查询&#xff0c;对GPT-4o的各种模态安全性进行了详细测试。 结果发现&#xff0c;GPT-4o新引入的语音模态带来了新的攻击面&#xff0c;多模态整体安全性不如GPT-4V。 GPT-4o…

SAP 使用BAPI更改分配字段ZUONR不生效解决方案

需求&#xff1a; 使用BAPI变更财务凭证上的ZUONR分配字段&#xff0c;正常情况下使用BAPI:FI_DOCUMENT_CHANGE或者FI_ITEMS_MASS_CHANGE都是可以进行变更的&#xff0c;但是项目上要变更的科目类型是KZ&#xff0c;导致这两个BAPI都没办法进行更改&#xff0c;故对此BAPI进行…

Kali Linux 2022.2 发布,包含 10 个新工具和WSL 改进

Offensive Security发布了Kali Linux 2022.2&#xff0c;这是2022年的第二个版本&#xff0c;具有桌面增强功能&#xff0c;有趣的愚人节屏幕保护程序&#xff0c;WSL GUI改进&#xff0c;终端调整&#xff0c;最重要的是&#xff0c;新的工具&#xff01; Kali Linux是一个Li…

中电金信:产教联合共育人才 AFAC2024金融智能创新大赛启动

当前&#xff0c;人工智能技术正在蓬勃发展&#xff0c;引领着各行各业迈向智能化的新纪元&#xff0c;特别是在金融科技领域&#xff0c;伴随人工智能技术的不断迭代与突破&#xff0c;金融服务的边界也在不断拓展&#xff0c;传统的金融业态正经历着深刻的变革与重塑。 与此同…

SpringCash

文章目录 简介引入依赖常用注解application.yml使用1. 启动类添加注解使用方法上添加注解 简介 Spring Cache是一个框架&#xff0c;实现了基于注解的缓存功能底层可以使用EHCache、Caffeine、Redis实现缓存。 注解一般放在Controller的方法上&#xff0c;CachePut 注解一般有…

给文件夹加密的最简单方法

安当TDE透明加密针对文件夹数据加密的保护方案主要包括以下几个方面&#xff1a; 1. 透明加密机制&#xff1a; 用户无需关心数据的加密和解密过程&#xff0c;操作文件夹时就像处理普通数据一样。加密和解密操作在后台自动进行&#xff0c;对用户和应用程序透明。 2. 高性能加…

【LeetCode 前缀和 + 哈希表】LC_560_和为K的子数组

文章目录 1. 和为K的子数组&#x1f197; 1. 和为K的子数组&#x1f197; 题目链接&#x1f517; &#x1f427;解题思路&#xff1a; 前缀和 哈希表 &#x1f34e; 设i为数组中的任意位置&#xff0c;⽤ sum[i] 表⽰ [0, i] 区间内所有元素的和。 &#x1f34e; 想知道有…

Mybatis05-一对多和多对一处理

多对一和一对多 多对一 多对一的理解&#xff1a; 多个学生对应一个老师 如果对于学生这边&#xff0c;就是一个多对一的现象&#xff0c;即从学生这边关联一个老师&#xff01; 结果映射&#xff08;resultMap&#xff09;&#xff1a; association 一个复杂类型的关联&…

Spark安装、解压、配置环境变量、WordCount

Spark 小白的spark学习笔记 2024/5/30 10:14 文章目录 Spark安装解压改名配置spark-env.sh重命名&#xff0c;配置slaves启动查看配置环境变量 工作流程maven创建maven项目配置maven更改pom.xml WordCount按照用户求消费额上传到spark集群上运行 安装 上传&#xff0c;直接拖拽…

RPA-UiBot6.0数据分发机器人—工作通知一键分发

前言 &#x1f4e2;友友们本篇博客的焦点机器人&#xff1a;信息群发机器人&#x1f44b; &#xff08;可以参考小北之前的微信群发助手和校园网更新提示助手两篇博客&#xff09;Uibot (RPA设计软件&#xff09;智能识别信息&#xff0b;微信群发助手&#xff08;升级版&…

Tomcat配置中最大线程数和句柄数分别意义和关系

哈喽&#xff0c;大家好&#xff0c;我是木头左&#xff01; 在Tomcat服务器的配置中&#xff0c;有两个参数是非常重要的&#xff1a;最大线程数和最大句柄数。这两个参数对于服务器的性能和稳定性有着至关重要的影响。本文将详细介绍这两个参数的意义和关系。 1. 最大线程数 …

样式的双向绑定的2种方式,实现样式交互效果

与样式标签实现双向绑定 通过布尔值来决定样式是出现还是消失 show代表着布尔值&#xff0c;show的初始值是false所以文本不会有高亮的效果&#xff0c;当用户点击了按钮&#xff0c;就会调用shows这个函数&#xff0c;并将show的相反值true赋值并覆盖给show,此时show的值为tru…

LangChain入门学习笔记(二)——LangChain表达式语言(LCEL)

基于LangChain框架编写大模型应用的过程就像垒积木&#xff0c;其中的积木就是Prompts&#xff0c;LLMs和各种OutputParser等。如何将这些积木组织起来&#xff0c;除了使用基本Python语法调用对应类的方法&#xff0c;一种更灵活的方法就是使用位于LangChain-Core层中的LCEL&a…

一篇文章彻底搞懂Maven

一、Maven简介 1-Maven介绍 https://maven.apache.org/what-is-maven.html Maven 是自动化构建工具。 Maven 是 Apache 软件基金会组织维护的一款自动化构建工具&#xff0c;专注服务于 Java 平台的项目构建和依赖管理。Maven 这个单词的本意是&#xff1a;专家&#xff0c;内…

这些代码是APP自动化插件开发的关键!

在移动互联网高速发展的今天&#xff0c;APP的自动化插件开发成为了提升应用功能性和用户体验的重要手段。 而在这一过程中&#xff0c;五段源代码的巧妙运用往往能够起到事半功倍的效果&#xff0c;本文将为您科普分享这五段关键的源代码&#xff0c;帮助您更好地理解和应用自…

【Unity】RPG2D龙城纷争(二)关卡、地块

更新日期&#xff1a;2024年6月12日。 项目源码&#xff1a;在第四章发布 索引 简介地块&#xff08;Block&#xff09;一、定义地块类二、地块类型三、地块渲染四、地块索引 关卡&#xff08;Level&#xff09;一、定义关卡类二、关卡基础属性三、地块集合四、关卡初始化五、关…

EDEX-UI这个终端模拟器

eDEX-UI 是一款开源、免费、跨平台的全屏终端模拟器和系统监视器&#xff0c;外观和操作界面极其科幻&#xff0c;灵感来自电影《创战纪》的会议室特效场景。作者倾注了大量心血&#xff0c;使得它不仅拥有酷炫的操作界面&#xff0c;还具备清晰爽脆的音效。 优点&#xff1a; …

使用 PNPM 从 0 搭建 monorepo,测试并发布

1 目标 通过 PNPM 创建一个 monorepo&#xff08;多个项目在一个代码仓库&#xff09;项目&#xff0c;形成一个通用的仓库模板。 这个仓库既可以用于公司存放和管理所有的项目&#xff0c;也可以用于将个人班余的所有积累整合其中。 2 环境要求 核心是 PNPM 和 Node.js&…

万字长文讲解Linux内存管理:伙伴系统

1. buddy system简介&#xff1a; 伙伴系统是内核中用来管理物理内存的一种算法&#xff0c;我们知道内存中有一些是被内核代码占用&#xff0c;还有一些是被特殊用途所保留&#xff0c;那么剩余的空闲内存都会交给内核内存管理系统来进行统一管理和分配。 内核中会把内存按照…

nodejs——原型链污染

一、引用类型皆为对象 原型和原型链都是来源于对象而服务于对象的概念&#xff0c;所以我们要先明确一点&#xff1a; JavaScript中一切引用类型都是对象&#xff0c;对象就是属性的集合。 Array类型、Function类型、Object类型、Date类型、RegExp类型等都是引用类型。 也就…