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

打印 上一主题 下一主题

主题 869|帖子 869|积分 2607

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

@
目次

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

既然我们要学习:”Spring IoC注解式开发“,自然就是要是用上注解 的,为了方便后面的学习,这里我们简单回顾一下注解的内容。更多关于注解方面的内容大家可以移步至:✏️✏️✏️ Java “框架 = 注解 + 反射 + 设计模式” 之 注解详解-CSDN博客
  1. 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集合中。


  1. 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();}
复制代码
  1. package com.rainbowsea;////@Component(value = "userBean",属性名 = 属性值,属性名 = 属性值,属性名 = 属性值...)//@Component(value = "userBean")// 如果属性名是 value,value 可以省略@Component("userBean")public class User {}
复制代码
  1. package com.rainbowsea;@Component("orderBean")public class Order {}
复制代码

  1. 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("\\.")[0]);            // 拼接成:全限定类名            String className = packageName + "." + file1.getName().split("\\.")[0];            // 再通过反射机制,解析注解            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);    }}
复制代码
运行结果:

3. Spring 声明Bean的注解

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

  • @Compoent


  • @Controller


  • @Service


  • @Repository

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

  • 控制器类上利用:Controller
  • service类上利用:Service
  • dao类上利用:Repository
他们都是只有一个value属性。value属性用来指定bean的id,也就是bean的名字

3.1 Spring注解的利用

如何利用以上的注解呢?



    • 第一步:到场aop的依靠



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



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



    • 第四步:在Bean类上利用注解

第一步:到场aop的依靠
照旧第一步,通过Maven 导入相关的 jar 包,在 pom.xml  文件当中。
  1.     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的依靠。以是这一步不消做。

第二步:在配置文件中添加context命名空间
注意:这里所说的配置文件是指,我们配置 bean 对象的谁人配置.xml 的配置文件信息。如下:
  1. [/code][b]第三步:在配置文件中指定扫描的包[/b]
  2. 注意:这里所说的配置文件是指,我们配置 bean 对象的谁人配置.xml 的配置文件信息。如下:
  3. [b]指定扫描的包:[/b] 是指明Spring 在谁人包路径下,可以找到要实例化的 Bean 对象。
  4. [align=center][img]https://img2024.cnblogs.com/blog/3084824/202405/3084824-20240505214344442-500331598.png[/img][/align]
  5. [align=center][img]https://img2024.cnblogs.com/blog/3084824/202405/3084824-20240505214344716-668328747.png[/img][/align]
  6. [code]   
复制代码
  1.    
复制代码
第四步:在Bean类上利用注解
如下:上面四个注解(@Controller、@Service、@Repository @Component),我们都利用测试上,看看能否实例化乐成。

  1. package com.rainbowsea.reflect.sprint.bean;import org.springframework.stereotype.Service;//@Service(value = "orderBean")@Service("os")public class Order {}
复制代码
  1. package com.rainbowsea.reflect.sprint.bean;import org.springframework.stereotype.Repository;@Repository("studentBean")public class Student {}/** * 以上的 @Repository就相当域以下的配置信息 *  */
复制代码
  1. package com.rainbowsea.reflect.sprint.bean;import org.springframework.stereotype.Component;@Component(value = "userBean")public class User {}
复制代码
  1. package com.rainbowsea.reflect.sprint.bean;import org.springframework.stereotype.Controller;@Controller(value = "vipBean")public class Vip {}
复制代码
  1. 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 特殊的:如果要扫描的是多个包

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

  • 如果你要配置,扫描多个包下的文件可以利用逗号分隔开来
  • 或者是上一级一些,不外,大概会牺牲一点效率,查找的时间上多一些。

  1.    
复制代码
  1.         
复制代码
测试:


或者是上一级一些,不外,大概会牺牲一点效率,查找的时间上多一些。如下:
  1.         
复制代码
  1.         
复制代码

3.1.2 Spring 选择性实例化Bean对象

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


而只有在  的标签下的,指明的: 说明的注解才会生效,才会实例化该包下的 Bean 对象。注意此中的值是:include-filter,type="annotation",expression="org.springframework.stereotype.Controller" 注意:这个包名路径不要错了。org.springframework.stereotype.Controller
  1.                         
复制代码


测试:这里我们让注解是:@Service,@Controller 的这个两个有效,实例化Bean 对象,其他的注解失效,不实例化Bean 对象。

  1.                         
复制代码
  1.                                 
复制代码
运行测试:

第二种方案:
use-default-filters=" 属性,并该属性指为 true (为true 值是默认的,可以省略不写)。表示该表明的包下的所有带有声明Bean (@Component,@Controller,@Service,@Repository)的注解全部生效实例化该包下的 bean 对象。

<blockquote>
而在  的标签下的,指明的:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

农妇山泉一亩田

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表