农妇山泉一亩田 发表于 2024-5-20 20:43:32

Spring IoC注解式开发无敌详细(细节丰富)

1. Spring IoC注解式开发无敌详细(细节丰富)

@
目次

[*]1. Spring IoC注解式开发无敌详细(细节丰富)
[*]每博一文案
[*]2. 注解回顾
[*]3. Spring 声明Bean的注解

[*]3.1 Spring注解的利用

[*]3.1.1 特殊的:如果要扫描的是多个包
[*]3.1.2 Spring 选择性实例化Bean对象

[*]3.2 通过注解实现“Spring的注入”

[*]3.2.1 @Value 注解的 Bean 赋值
[*]3.2.2 @Autowired 与 @Qualifier
[*]3.2.3 @Resource 注解实现赋值操作

[*]3.3 Spring 全注解式开发

[*]4. 总结:
[*]5. 疑问:
[*]6. 末了:

每博一文案

读书,它可以在我生存顺遂的时间,看见更大的世界,在生存不顺的时间,依然可以有心态去仰望星空。无论如果都不要将爱,转为成了某种恨就是我过的不好,也希望你过的好,就算我过的不好,我也依旧会帮你过的好不管你一天,经历了什么,天黑了,我带你回家。生命是有光的,在我熄灭已前,可以或许照亮你一点便是,我所有能做的了。2. 注解回顾

既然我们要学习:”Spring IoC注解式开发“,自然就是要是用上注解 的,为了方便后面的学习,这里我们简单回顾一下注解的内容。更多关于注解方面的内容大家可以移步至:✏️✏️✏️ Java “框架 = 注解 + 反射 + 设计模式” 之 注解详解-CSDN博客 。
import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target(value = {ElementType.TYPE})@Retention(value = RetentionPolicy.RUNTIME)public @interface Component {    String value();}以上是自定义了一个注解:Component
该注解上面修饰的注解包括:Target注解和Retention注解,这两个注解被称为元注解。
Target注解用来设置Component注解可以出现的位置,以上代表表示Component注解只能用在类和接口上。
Retention注解用来设置Component注解的保持性策略,以上代表Component注解可以被反射机制读取。
String value(); 是Component注解中的一个属性。该属性类型String,属性名是value。
注解赋值 ——》语法格式:@注解类型名(属性名=属性值, 属性名=属性值, 属性名=属性值......)
userBean为什么利用双引号括起来,由于value属性是String类型,字符串。
另外如果属性名是value,则在利用的时间可以省略属性名。
为了进一步,运用注解,这里我们看看下面这个需求。
现在只知道一个包com.rianbowsea 的名字,扫描这个包下所有的类,当这个类上有@Compoent 注解的时间,实例化该对象,然后放到Map集合中。
https://img2024.cnblogs.com/blog/3084824/202405/3084824-20240505214344650-531136874.png
https://img2024.cnblogs.com/blog/3084824/202405/3084824-20240505214344674-731420214.png
https://img2024.cnblogs.com/blog/3084824/202405/3084824-20240505214344679-788821197.png
package com.rainbowsea;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;// 利用某个注解的时间,如果注解的属性值是数组,而且数组中只有一个元素,大括号可以省略。@Target(ElementType.TYPE)// @Retention 也是一个元注解,用来标注@Component 注解最终保存在class 文件当中,而且可以被反射机制读取@Retention(RetentionPolicy.RUNTIME)public @interface Component {    // 定义注解的属性    // String 是属性类型    // value 是属性名    String value();}package com.rainbowsea;////@Component(value = "userBean",属性名 = 属性值,属性名 = 属性值,属性名 = 属性值...)//@Component(value = "userBean")// 如果属性名是 value,value 可以省略@Component("userBean")public class User {}package com.rainbowsea;@Component("orderBean")public class Order {}https://img2024.cnblogs.com/blog/3084824/202405/3084824-20240505214344614-1125945222.png
https://img2024.cnblogs.com/blog/3084824/202405/3084824-20240505214344595-1010362028.png
package com.rainbowsea;import java.io.File;import java.lang.reflect.Constructor;import java.lang.reflect.InvocationTargetException;import java.net.URL;import java.util.Arrays;import java.util.HashMap;import java.util.Map;public class ComponentScan {    /*    现在只知道一个包的名字,扫描这个包下所有的类,当这个类上有@Compoent 注解的时间,    实例化该对象,然后放到Map集合中   */    public static void main(String[] args) {      //定义一个集合存储此中的实例化对象      Map beanMap = new HashMap();      String packageName = "com.rainbowsea";      // 开始扫描程序      // .这个正则表达式表示任意字母,这里的“.” 必须是一个平凡的"."字符,不能是正则表达式中的“.”      // 在正则表达式当中怎么表示一个平凡的"." 字符呢?利用"\",在Java当中一个“/” 要用两个“//” 表示      String packagePath = packageName.replaceAll("\\.", "/");      //System.out.println(packagePath);      // com 是在类的根路径下的一个目次      //url 是一个绝对路径      URL url = ClassLoader.getSystemClassLoader().getResource(packagePath);      String path = url.getPath();      //System.out.println(path);      // 获取一个绝对路径下的所有文件      File file = new File(path);      File[] files = file.listFiles();      Arrays.stream(files).forEach(file1 -> {            //System.out.println(file1);            //System.out.println(file1.getName().split("\\."));            // 拼接成:全限定类名            String className = packageName + "." + file1.getName().split("\\.");            // 再通过反射机制,解析注解            Class aClass = null;            try {                aClass = Class.forName(className);            } catch (ClassNotFoundException e) {                throw new RuntimeException(e);            }            // 判断该类是否含有该 Component.class 注解            if(aClass.isAnnotationPresent(Component.class)) {                // 获取注解                Component annotation = aClass.getAnnotation(Component.class);                // 获取到该注解的值                String id = annotation.value();                // 有这个注解的都要创建对象                try {                  Constructor declaredConstructor = aClass.getDeclaredConstructor();                  Object obj= declaredConstructor.newInstance();                  // 将创建好的实例化对象存储到 Map 当前去。                  beanMap.put(id,obj);                } catch (Exception e) {                  e.printStackTrace();                  throw new RuntimeException(e);                }            }      });      System.out.println(beanMap);    }}运行结果:
https://img2024.cnblogs.com/blog/3084824/202405/3084824-20240505214344733-1569218380.png
3. Spring 声明Bean的注解

注解的存在重要是为了简化XML的配置。Spring6倡导全注解开发。
在Spring 当中,负责声明 Bean 的注解的,常见的有如下四个:

[*]@Compoent
https://img2024.cnblogs.com/blog/3084824/202405/3084824-20240505214344756-1402682937.png

[*]@Controller
https://img2024.cnblogs.com/blog/3084824/202405/3084824-20240505214344495-1023355571.png

[*]@Service
https://img2024.cnblogs.com/blog/3084824/202405/3084824-20240505214344627-1164720089.png

[*]@Repository
https://img2024.cnblogs.com/blog/3084824/202405/3084824-20240505214344441-825777747.png
通过源码可以看到,@Controller、@Service、@Repository 这三个注解都是@Component注解的别名。换句话说:这四个注解的功能都一样。用哪个都可以。
只是为了增强程序的可读性,建议:

[*]控制器类上利用:Controller
[*]service类上利用:Service
[*]dao类上利用:Repository
他们都是只有一个value属性。value属性用来指定bean的id,也就是bean的名字
https://img2024.cnblogs.com/blog/3084824/202405/3084824-20240505214344591-1159526599.png
3.1 Spring注解的利用

如何利用以上的注解呢?

[*]

[*]第一步:到场aop的依靠

[*]

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

[*]

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

[*]

[*]第四步:在Bean类上利用注解

第一步:到场aop的依靠
照旧第一步,通过Maven 导入相关的 jar 包,在 pom.xml文件当中。
    4.0.0    com.rainbowsea.reflect    spring6-oo8-anotation-blog    1.0-SNAPSHOT            17      17                            org.springframework            spring-context            6.0.11                                    junit            junit            4.13.2            test                            jakarta.annotation            jakarta.annotation-api            2.1.1            我们可以看到当到场spring-context依靠之后,会关联到场aop的依靠。以是这一步不消做。
https://img2024.cnblogs.com/blog/3084824/202405/3084824-20240505214344667-32085658.png
第二步:在配置文件中添加context命名空间
注意:这里所说的配置文件是指,我们配置 bean 对象的谁人配置.xml 的配置文件信息。如下:
https://img2024.cnblogs.com/blog/3084824/202405/3084824-20240505214344735-1089577790.png
第三步:在配置文件中指定扫描的包
注意:这里所说的配置文件是指,我们配置 bean 对象的谁人配置.xml 的配置文件信息。如下:
指定扫描的包: 是指明Spring 在谁人包路径下,可以找到要实例化的 Bean 对象。
https://img2024.cnblogs.com/blog/3084824/202405/3084824-20240505214344442-500331598.png
https://img2024.cnblogs.com/blog/3084824/202405/3084824-20240505214344716-668328747.png
        第四步:在Bean类上利用注解
如下:上面四个注解(@Controller、@Service、@Repository @Component),我们都利用测试上,看看能否实例化乐成。
https://img2024.cnblogs.com/blog/3084824/202405/3084824-20240505214344459-1793737610.png
https://img2024.cnblogs.com/blog/3084824/202405/3084824-20240505214344504-486545979.png
package com.rainbowsea.reflect.sprint.bean;import org.springframework.stereotype.Service;//@Service(value = "orderBean")@Service("os")public class Order {}package com.rainbowsea.reflect.sprint.bean;import org.springframework.stereotype.Repository;@Repository("studentBean")public class Student {}/** * 以上的 @Repository就相当域以下的配置信息 **/package com.rainbowsea.reflect.sprint.bean;import org.springframework.stereotype.Component;@Component(value = "userBean")public class User {}package com.rainbowsea.reflect.sprint.bean;import org.springframework.stereotype.Controller;@Controller(value = "vipBean")public class Vip {}https://img2024.cnblogs.com/blog/3084824/202405/3084824-20240505214344483-316055625.png
package com.rainbowsea.test;import com.rainbowsea.reflect.sprint.bean.Order;import com.rainbowsea.reflect.sprint.bean.Student;import com.rainbowsea.reflect.sprint.bean.User;import com.rainbowsea.reflect.sprint.bean.Vip;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class IoCAnnotationTest {    @Test    public void testIoCAnnotation() {      ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");      Order os = applicationContext.getBean("os", Order.class);      System.out.println(os);      Student studentBean = applicationContext.getBean("studentBean", Student.class);      System.out.println(studentBean);      User userBean = applicationContext.getBean("userBean", User.class);      System.out.println(userBean);      Vip vipBean = applicationContext.getBean("vipBean", Vip.class);      System.out.println(vipBean);    }}3.1.1 特殊的:如果要扫描的是多个包

特殊的: 如果要扫描的是多个包

[*]如果你要配置,扫描多个包下的文件可以利用逗号分隔开来 。
[*]或者是上一级一些,不外,大概会牺牲一点效率,查找的时间上多一些。https://img2024.cnblogs.com/blog/3084824/202405/3084824-20240505214344669-1577017470.png
          测试:
https://img2024.cnblogs.com/blog/3084824/202405/3084824-20240505214344611-379152919.png
https://img2024.cnblogs.com/blog/3084824/202405/3084824-20240505214344674-890683094.png
或者是上一级一些,不外,大概会牺牲一点效率,查找的时间上多一些。如下:
https://img2024.cnblogs.com/blog/3084824/202405/3084824-20240505214344780-1030048011.png
            https://img2024.cnblogs.com/blog/3084824/202405/3084824-20240505214344753-355148880.png
3.1.2 Spring 选择性实例化Bean对象

假设在某个包下有很多Bean,有的Bean上标注了@Component,有的标注了@Controller,有的标注了@Service,有的标注了@Repository,现在由于某种特殊业务的需要,只允许此中所有的Controller加入Bean管理,其他的都不实例化。这应该怎么办呢?
我们可以有一下两种方案:
第一种方案:
在扫描文件的: 的标签当中添加上:use-default-filters=" 属性,并该属性指为 false 。表示该表明的包下的所有带有声明Bean (@Component,@Controller,@Service,@Repository)的注解全部失效。不会实例化该包下的 bean 对象。

[*]https://img2024.cnblogs.com/blog/3084824/202405/3084824-20240505214344533-1732108683.png
而只有在的标签下的,指明的: 说明的注解才会生效,才会实例化该包下的 Bean 对象。注意此中的值是:include-filter,type="annotation",expression="org.springframework.stereotype.Controller" 注意:这个包名路径不要错了。org.springframework.stereotype.Controller
https://img2024.cnblogs.com/blog/3084824/202405/3084824-20240505214344667-1497930748.png
                        

[*]
测试:这里我们让注解是:@Service,@Controller 的这个两个有效,实例化Bean 对象,其他的注解失效,不实例化Bean 对象。
https://img2024.cnblogs.com/blog/3084824/202405/3084824-20240505214344569-1257024183.png
https://img2024.cnblogs.com/blog/3084824/202405/3084824-20240505214344658-1839275923.png
                                                      运行测试:
https://img2024.cnblogs.com/blog/3084824/202405/3084824-20240505214344622-1742788053.png
第二种方案:
use-default-filters=" 属性,并该属性指为 true (为true 值是默认的,可以省略不写)。表示该表明的包下的所有带有声明Bean (@Component,@Controller,@Service,@Repository)的注解全部生效。会实例化该包下的 bean 对象。
https://img2024.cnblogs.com/blog/3084824/202405/3084824-20240505214344658-1419154428.png
<blockquote>
而在的标签下的,指明的:
页: [1]
查看完整版本: Spring IoC注解式开发无敌详细(细节丰富)