【Spring进阶系列丨第七篇】Spring框架新注解分类及详解

2024-04-10 1225阅读

文章目录

  • 一、Spring新注解
    • 1.1、Configuration注解
      • 1.1.1、定义一个类
      • 1.1.2、使用Configuration注解修饰类
      • 1.1.3、作用
      • 1.2、Bean注解
        • 1.2.1、定义bean
        • 1.2.2、在主配置类中注册bean
        • 1.2.3、测试容器中是否有该bean
        • 1.2.4、注册bean的同时可以指定bean名称
        • 1.2.5、补充内容
          • 1.2.5.1、案例1【方法有参数】
          • 1.2.5.2、案例2
          • 1.3、ComponentScan注解
            • 1.3.1、案例1
            • 1.3.2、案例2
            • 1.3.3、案例3
            • 1.4、Scope注解
              • 1.4.1、定义Bean
              • 1.4.2、注册Bean并定义作用域
              • 1.4.3、测试
              • 1.4.4、将Bean的作用域改为多例
              • 1.4.5、测试1
              • 1.4.6、测试2
              • 1.5、Lazy注解
                • 1.5.1、注册Bean
                • 1.5.2、测试
                • 1.5.3、总结
                • 1.6、Conditional注解【了解】
                  • 1.6.1、定义两个Bean
                  • 1.6.2、定义两个类实现Condition接口
                  • 1.6.3、注册Bean
                  • 1.6.4、测试1
                  • 1.6.5、测试2
                  • 1.6.6、总结
                  • 1.7、Import注解
                    • 1.7.1、用法一
                      • 1.7.1.1、定义Bean
                      • 1.7.1.2、注册Bean
                      • 1.7.1.3、测试容器中是否有该Bean
                      • 1.7.1.4、注意
                      • 1.7.2、用法二
                        • 1.7.2.1、定义Bean
                        • 1.7.2.2、新建配置类并注册Bean
                        • 1.7.2.3、Import导入配置类
                        • 1.7.2.4、测试容器有哪些Bean
                        • 1.7.2.5、总结
                        • 1.8、PropertySource注解
                          • 1.8.1、定义Pig.properties文件
                          • 1.8.2、主配置类
                          • 1.8.3、测试
                          • 好书推荐

                            【Spring进阶系列丨第七篇】Spring框架新注解分类及详解

                            一、Spring新注解

                            1.1、Configuration注解

                            1.1.1、定义一个类

                            public class SpringMainConfig {
                            }
                            

                            1.1.2、使用Configuration注解修饰类

                            @Configuration
                            public class SpringMainConfig {
                                
                            }
                            

                            1.1.3、作用

                            ​ 使用Configuration注解修饰的类表示的是:当前类是一个配置类。该类的作用和beans.xml是一样的,换句话说,该注解所修饰的类就是用来代替beans.xml文件的。

                            1.2、Bean注解

                            1.2.1、定义bean

                            public class User {
                                
                                private Integer id;
                                
                                private String name;
                                public User(Integer id, String name) {
                                    this.id = id;
                                    this.name = name;
                                }
                            }
                            

                            1.2.2、在主配置类中注册bean

                            ​ 在以前,使用xml去注册bean的时候,使用的是bean标签,形如:

                             
                            

                            ​ 现在改为使用注解,使用的是@Bean注解。

                            @Configuration
                            public class SpringMainConfig {
                                
                                // 给容器中注册一个bean;类型为方法返回值的类型,默认方法名作为id,即bean的名字默认是方法名
                                @Bean
                                public User user(){
                                    return new User(1,"段康家");
                                }
                            }
                            

                            1.2.3、测试容器中是否有该bean

                            @Test
                            public void testUser() throws Exception{
                                ApplicationContext ac = new AnnotationConfigApplicationContext(SpringMainConfig.class);
                                User user = (User) ac.getBean("user");
                                System.out.println(user);	// User{id=1, name='段康家'}
                            }
                            

                            1.2.4、注册bean的同时可以指定bean名称

                            @Configuration
                            public class SpringMainConfig {
                                // 给容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id
                              	// 可以再注册Bean的同时,不用方法名作为id,可以指定bean的名称。
                                @Bean("user01")
                                public User user(){
                                    return new User(1,"段康家");
                                }
                            }
                            

                            1.2.5、补充内容

                            1.2.5.1、案例1【方法有参数】
                            // 定义UserDao接口
                            public interface UserDao {
                            }
                            
                            // 定义UserDao接口的实现类
                            public class UserDaoImpl01 implements UserDao{
                            }
                            
                            // 定义UserService
                            public class UserServiceImpl {
                                private UserDao userDao;
                            	
                              	// 构造方法接收UserDao类型的对象
                                public UserServiceImpl(UserDao userDao){
                                    this.userDao = userDao;
                                }
                            }
                            

                            重点看主配置类:

                            @Configuration
                            public class SpringMainConfig {
                                // 给容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id
                                @Bean
                                public UserServiceImpl userService(UserDao userDao){
                                    return new UserServiceImpl(userDao);
                                }
                                @Bean
                                public UserDao userDao01(){
                                    return new UserDaoImpl01();
                                }
                            }
                            
                             @Test
                            public void testUser() throws Exception{
                              	ApplicationContext ac = new AnnotationConfigApplicationContext(SpringMainConfig.class);
                                UserServiceImpl userService = (UserServiceImpl) ac.getBean("userService");
                                System.out.println(userService);
                            }
                            

                            说明:测试后发现程序能够正常运行,说明UserDao能够正常的以构造函数参数的形式注入到UserServiceImpl类中。

                            总结:当我们使用Bean注解配置方法时,如果方法有参数,spring框架会去容器中查找有没有可用的bean对象。查找的方式和Autowired注解的作用是一样的。即:Spring会从容器中根据类型注入

                            1.2.5.2、案例2

                            当然还有一种情况是:容器中注册了多个相同类型的Bean,那么Spring又是如何注入的呢?在8.2.5.1案例基础之上再添加一个UserDaoImpl02。

                            public class UserDaoImpl02 implements UserDao{
                            }
                            

                            在再主配置类中注册该UserDaoImpl02的Bean.

                            【Spring进阶系列丨第七篇】Spring框架新注解分类及详解

                            通过看图可以知道,有问题,不能够实现自动注入,该怎么办呢?两种方式:

                            a、修改方法的参数

                            【Spring进阶系列丨第七篇】Spring框架新注解分类及详解

                            b、指定Bean的名称

                            【Spring进阶系列丨第七篇】Spring框架新注解分类及详解

                            总结:本质上来说,解决方案1和解决方案2是一样的。

                            c、使用Qualifier注解。

                            ​ 实际上在7.3.2章节中,已经讲到了关于Qualifier注解的使用,通过该注解实现的功能是:当系统中存在多个相同类型的bean的时候,Spring就会注入失败,这个时候就需要再根据名称实现注入,而使用Qualifier注解可以达到根据给定名称的bean实现注入 。在以前讲解的过程中,我们是把该注解应用到了对类的成员变量上 ,但是需要注意的细节是:该注解应用到成员变量上时,注入时不能单独使用,需要搭配Autowired注解 。 但是,这里有一个例外,那么就是该注解也可以应用在方法参数上。

                            【Spring进阶系列丨第七篇】Spring框架新注解分类及详解

                            ​ 特别注意:当把Qualifier注解应用在方法参数上时,可以单独使用

                            1.3、ComponentScan注解

                            ==作用:==指定spring在创建容器时要扫描的包。作用就如同在配置文件中这样的定义:

                            	
                            
                            

                            1.3.1、案例1

                            第一步:定义三个Bean,分别是CatController、CatService、CatMapper,并分别用@Controller、@Service、@Repository修饰。

                            package cn.bdqn.controller;
                            @Controller
                            public class CatController {
                                
                            }
                            
                            package cn.bdqn.service;
                            @Service
                            public class CatServiceImpl {
                            }
                            
                            package cn.bdqn.mapper;
                            @Repository
                            public class CatMapper {
                                
                            }
                            

                            第二步:要想真正的注册到容器中,就必须要让容器扫描到此注解所修饰的类所在的包。

                            @Configuration
                            @ComponentScan(value = {"cn.bdqn"})
                            public class SpringMainConfig {
                            }
                            

                            第三步:测试容器中是否注册了该bean。

                            @Test
                            public void testComponentScan() throws Exception{
                                ApplicationContext ac = new AnnotationConfigApplicationContext(SpringMainConfig.class);
                                // 获取Spring容器中已经注册好的bean,把所有bean的名字获取出来
                                String[] names = ac.getBeanDefinitionNames();
                                for (String name:names) {
                                    System.out.println(name);
                                }
                            }
                            /**
                            	结果:
                            		catController
                                    catMapper
                                    catServiceImpl
                            */
                            

                            总结:默认情况下,Spring会扫描cn.bdqn包以及子包下面所有的使用@Controller、@Service、@Repository、@Component所修饰的bean注册到容器中

                            1.3.2、案例2

                            **需求:**我现在不想扫描被@Controller所修饰的类注册到容器中,即让Spring扫描不到即可。言外之意就是:把所有被@Controller所修饰的类给排除掉。

                            说明:定义的CatController、CatServiceImpl、CatMapper不变,使用的是案例1。唯一要修改的配置是主配置文件类。为@ComponentScan注解添加excludeFilters属性即可。

                            **含义:**excludeFilters的作用指定扫描的时候按照什么规则排除那些组件。

                            **做法:**修改主配置类,即

                            @Configuration
                            @ComponentScan(
                              value = {"cn.bdqn"},
                              excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,
                                                                      value = {Controller.class})
                                               }
                            )
                            public class SpringMainConfig {
                              
                            }
                            

                            **测试:**测试代码同案例1

                            /**
                            	catMapper
                            	catServiceImpl
                            **/
                            

                            1.3.3、案例3

                            **需求:**我现在只想扫描被@Controller所修饰的类注册到容器中,被其他修饰的注解不扫描。

                            说明:定义的CatController、CatServiceImpl、CatMapper不变,使用的是案例1。唯一要修改的配置是主配置文件类。为@ComponentScan注解添加includeFilters属性即可。

                            **含义:**includeFilters的作用指定扫描的时候只需要包含哪些组件。

                            **做法:**修改主配置类,即

                            @Configuration
                            @ComponentScan(value = {"cn.bdqn"},
                                           includeFilters = {
                                                @ComponentScan.Filter(type = FilterType.ANNOTATION,
                                                                      value = {Controller.class, Service.class})}
                            )
                            public class SpringMainConfig {
                            }
                            

                            **测试:**测试代码同案例1

                            /**
                            	catController
                                catMapper
                                catServiceImpl
                                测试,发现,不仅仅Controller被扫描进来了,包括Service,Mapper也都扫描进来了,好像不起作用,没有生效,原因是在于在使用includeFilters做只包含的时候,还需要关闭默认的过滤规则【在默认情况下,Spring是扫描指定包及子包下的被@Component、@Controller、@Service等bean的。】
                            */
                            

                            主配置文件类修改如下:

                            @Configuration
                            @ComponentScan(value = {"cn.bdqn"},
                                           includeFilters = {
                                                @ComponentScan.Filter(type = FilterType.ANNOTATION,
                                                                      value = {Controller.class, Service.class})},
                                           useDefaultFilters = false
                            )
                            public class SpringMainConfig {
                            }
                            

                            测试:

                            /**
                            	catController
                            	测试发现:结果正常,符合预期结果,只扫描到了Controller注解。
                            */
                            

                            1.4、Scope注解

                            ​ 作用:可以改变bean的作用域。在Spring中,Bean的默认作用域是单例的。

                            1.4.1、定义Bean

                            public class User {
                                private Integer id;
                                private String name;
                                public User(Integer id, String name) {
                                    this.id = id;
                                    this.name = name;
                                }
                            }
                            

                            1.4.2、注册Bean并定义作用域

                            @Configuration
                            public class SpringMainConfig {
                                @Bean
                                @Scope
                                public User user(){
                                  	System.out.println("对象创建啦");
                                    return new User(1,"HelloWorld");
                                }
                            }
                            

                            1.4.3、测试

                             @Test
                            public void testComponentScan() throws Exception{
                              	ApplicationContext ac = new AnnotationConfigApplicationContext(SpringMainConfig.class);
                            }
                            /**
                            	对象创建啦
                            */
                            

                            ​ 结果:注册的Bean默认是单实例的,Spring容器将会在启动的时候调用方法创建对象后放入容器中,以后每次需要拿对象了就直接从容器中拿,而且每次拿的还是同一个。

                            1.4.4、将Bean的作用域改为多例

                            @Configuration
                            public class SpringMainConfig {
                                @Bean
                                @Scope("prototype")
                                public User user(){
                                    System.out.println("对象创建啦");
                                    return new User(1,"HelloWorld");
                                }
                            }
                            

                            1.4.5、测试1

                            @Test
                            public void testPrototype() throws Exception{
                              	ApplicationContext ac = new AnnotationConfigApplicationContext(SpringMainConfig.class);
                            }
                            /**
                            	测试后发现容器启动的时候,多例对象并不会创建。
                            */
                            

                            1.4.6、测试2

                             @Test
                            public void testPrototype() throws Exception{
                              ApplicationContext ac = new AnnotationConfigApplicationContext(SpringMainConfig.class);
                              User user01 = (User) ac.getBean("user");
                              User user02 = (User) ac.getBean("user");
                            }
                            /**
                            	对象创建啦
                            	对象创建啦
                            */
                            

                            ​ 总结:对于多实例来说,Spring容器在启动的时候并不会去调用方法创建对象并放在容器中,而是每次获取的时候才会调用方法创建对象,并且每次获取到的对象还不一样。

                            1.5、Lazy注解

                            作用:用此注解修饰的Bean表示的该Bean需要被懒加载,即不会随着Spring容器的启动而去创建。

                            1.5.1、注册Bean

                            @Configuration
                            public class SpringMainConfig {
                                @Bean
                                @Lazy(value = true)	// 开启懒加载
                                public User user(){
                                    System.out.println("对象创建啦");
                                    return new User(1,"HelloWorld");
                                }
                            }
                            

                            1.5.2、测试

                            @Test
                            public void testSingleton() throws Exception{
                               ApplicationContext ac = new AnnotationConfigApplicationContext(SpringMainConfig.class);
                            }
                            /**
                            	控制台什么都没有输出,因为我们的Bean被Layz注解修饰了,即使Spring容器启动了,我们的Bean也不会去创建,只有等到了真正要用到该bean了才去创建。
                            */
                            

                            1.5.3、总结

                            • 这个Lazy注解是针对单实例Bean才有效,因为也只有单实例Bean才会默认在容器启动的时候创建对象。
                            • 懒加载:容器启动不创建对象,只有在第一次使用(获取)Bean的时候采取创建对象,并初始化。
                            • 该注解的作用等价于。

                              1.6、Conditional注解【了解】

                              作用: 根据一定的条件进行判断,当满足这个条件时给容器注入Bean。

                              ==位置:==既可以修饰类也可以修饰方法。

                              ==需求:==当前操作系统如果是window,则注入WindoBean,如果是linux系统,则注入LinuxBean。

                              首先查看下@Conditional注解的源代码,即:

                              public @interface Conditional {
                                	// 该注解的属性值是一个Class类型的数组,数组的Class元素类型必须继承Condition接口,即元素的类型必
                                	// 须是Condition类型。
                              	Class
VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]