当前位置: 首页> 财经> 访谈 > 贵州seo排名_深圳工程建设交易服务中心网站_四种基本营销模式_企业培训员工培训平台

贵州seo排名_深圳工程建设交易服务中心网站_四种基本营销模式_企业培训员工培训平台

时间:2025/7/12 23:16:45来源:https://blog.csdn.net/2301_79184547/article/details/147287365 浏览次数:0次
贵州seo排名_深圳工程建设交易服务中心网站_四种基本营销模式_企业培训员工培训平台

在 Spring IoC& DI 详解 中对 IoC已经有了介绍,下面对 IoC 进行详细介绍。

IoC,即控制反转,在之前我们编写程序的时候,我们都是自己 new 出来一个对象,然后自己去管理这个对象,但是这有时候有些麻烦,那么我们可以将这些对象交给 Spring 进行管理,就相当于将对象的控制权交给 Spring,即控制反转。那么,我们应该如何将对象交给 Spring 管理呢?

Spring 的一大特点就是使用注解,在这里也是一样,使用类注解或者方法注解将对象交给 Spring 去管理。下面来一一介绍这些注解。

一、类注解

分为 @Controller,@Service,@Repository,@Component,@Configuration。

既然是类注解,就是指定在类上面的。

相同点:

这几个注解在使用方面没有太大区别,现使用 @Component 来进行讲解。

现有一个 StudentComponent 类,如下:

@Component
public class StudentComponent {public void method() {System.out.println("component");}
}

现在我们想要拿到这个类的一个对象,就需要使用如下方法:

@SpringBootApplication
public class SpringBootDemo2025416Application {public static void main(String[] args) {//获取 Spring 上下文对象ApplicationContext context = SpringApplication.run(SpringBootDemo2025416Application.class, args);//根据类型获取StudentComponent student1 = context.getBean(StudentComponent.class);student1.method();//根据名称获取,需要进行类型转换StudentComponent student2 = (StudentComponent) context.getBean("studentComponent");student2.method();//根据类型和名曾获取StudentComponent student3 = context.getBean("studentComponent", StudentComponent.class);student1.method();}}

这个类是 Spring 的启动类,我们在 conten 中获取我们交给 Spring 进行管理的对象。

代码运行结果如下:

通过上面的例子,我们可以知道,从 Spring 中获取对象的方式有三种,即:根据类型获取、根据对象名称获取、根据类型和对象名称获取。

在这里我们需要注意,我们并没有给这个对象指定名称,但为什么还能通过名称获取到这个对象呢?

在 Spring 中,会根据类名分配一个默认的对象名,规则如下:

1)类的首字母是大写的,其后的字母是小写的,如 StudentComponent,那么默认的对象名就是 studentComponent;

2)类的前两个首字母都是大写的,如 ABComponent,那么默认的对象名就是类名本身;

针对上面获取对象的方法,如果有多个对象,那么 Spring 就无法区分需要获取的是哪个对象,那么就会报错,这是我们就需要指定对象名称,这在后面的 @Bean 注解会进行讲解。

这里我们需要思考一下,上面的三个对象是同一个对象吗,还是不同的对象?我们可以将这三个对象的地址打印出来,结果如下:

从上图可以看出,这三个对象是同一个对象。

如果我们去掉 @Component 注解,会发生什么呢?

代码运行结果如下:

Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.gjm.demo.component.StudentComponent' availableat org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:343)at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:334)at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1261)at com.gjm.demo.SpringBootDemo2025416Application.main(SpringBootDemo2025416Application.java:17)

这是错误信息,异常为 NoSuchBeanDefinitionException,即在容器中找不到 StudentComponent 对象。这是因为由于我们要从容器中去获取一个对象,这就需要容器中必须得先存在这个对象才能去获取,加了 @Component 注解就相当于将这个对象放到了容器中,这个我们才能在容器中获取到这个对象。

不同点:

在上面我们说了这五个注解的相同用法,接下来开始介绍这五个注解的不同点。

@Controller 用于控制层;

@Service 用于业务逻辑层;

@Repository 用于数据层;

@Configuration 用于配置层;

@Component 用于组件层。

在实际应用中,这五个注解的边界并不是很清晰,虽然可以混用,但不同的注解表示这个类的不同的涵义,最好按照规定使用注解。

但是 @Controller 不能与其他注解提婚,这个注解是进行前后端交互用的,其他的注解都没有这个功能。

接下来我们看一下这五个注解的源码:

@Controller

@Service

@Repository

@Configuration

@Component

通过查看源码可以知道,@Controller, @Service,@Repository,@Configuration这四个注解中均含有 @Component 注解,即这四个注解均是 @Component 的衍生注解。

二、方法注解 

通过上面的介绍我们可以看出,无论我们怎么获取对象,这些对象均是同一个对象,但如果我们有多个对象呢,上面的注解就不管用了。下面介绍一个方法注解 @Bean。

既然是方法注解,那么就是指定在方法上的。

接下来来看一段代码:

public class StudentComponent {@Beanpublic Student s1() {return new Student("zhangsan", 12);}@Beanpublic Student s2() {return new Student("lisi", 14);}
}@SpringBootApplication
public class SpringBootDemo2025416Application {public static void main(String[] args) {//获取 Spring 上下文对象ApplicationContext context = SpringApplication.run(SpringBootDemo2025416Application.class, args);Student student1 = (Student)context.getBean("s1");System.out.println(student1);Student student2 = (Student)context.getBean("s2");System.out.println(student2);}}

当我们运行这段代码后,发现报错了,错误代码如下:

Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 's1' availableat org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:895)at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1362)at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1243)at com.gjm.demo.SpringBootDemo2025416Application.main(SpringBootDemo2025416Application.java:18)

里面说没有发现与一个名为 s1 的对象,那为什么我们加了 @Bean 注解,却说没有这个对象呢?

因为 @Bean 需要搭配类注解来使用,即在 StudentComponent 上面还需要加上一个类注解,上述的五大注解均可以使用,这里我么选择 @Component。

改动过的代码如下:

@Component
public class StudentComponent {@Beanpublic Student s1() {return new Student("zhangsan", 12);}@Beanpublic Student s2() {return new Student("lisi", 14);}
}@SpringBootApplication
public class SpringBootDemo2025416Application {public static void main(String[] args) {//获取 Spring 上下文对象ApplicationContext context = SpringApplication.run(SpringBootDemo2025416Application.class, args);Student student1 = (Student)context.getBean("s1");System.out.println(student1);Student student2 = (Student)context.getBean("s2");System.out.println(student2);}}

接下来就可以获取到 s1 与 s2 这两个对象了,下面是代码的运行结果:

下面来看一下 @Bean 的源码:

我们可以知道,这里面有两个属性,value 和 name,这两个属性表示的含义均为对象的名称,即我们可以自定义对象的名称,这个名称可以是一个字符串,也可以是一个字符串数组,代码如下:

    @Bean({"s3", "s4"})@Bean("s3")public Student s1() {return new Student("zhangsan", 12);}

 这里写了两个 @Bean,在实际情况下只能只用一个。现针对 @Bean("s3") 进行讲解。

当我们将对象名称改了之后,若我们还是按照原来默认的名字去获取,代码的运行结果如下:

Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 's1' availableat org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:895)at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1362)at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1243)at com.gjm.demo.SpringBootDemo2025416Application.main(SpringBootDemo2025416Application.java:18)

代码运行错误,错误信息里说没有找到一个对象名称叫做 s1 的,因为当我们将对象名改名后,原本的对象名就无法使用,必须使用改动之后的名称,下面使用 s3 来获取对象,代码运行结果如下:

结果运行成功。 

但是在 s1 中,我们对 student 的属性是直接赋值的,当然,也可以通过传递参数来赋值,代码如下:

@Component
public class StudentComponent {//    @Bean({"s3", "s4"})@Bean("s3")public Student s1(String name) {return new Student(name, 12);}@Beanpublic Student s2() {return new Student("lisi", 14);}
}

但是,我们在 getBean 方法中,并没有找到一个方法可以给对象传递参数,那么应该怎么给 name 赋值呢?

在这种情况下,当我们将对象交给 Spring 进行管理,那么 Spring 就会在 Spring 容器中查找 String 类型的对象,并将对象赋给 name,代码如下:

@Component
public class StudentComponent {//    @Bean({"s3", "s4"})@Bean("s3")public Student s1(String name) {return new Student(name, 12);}@Beanpublic Student s2() {return new Student("lisi", 14);}//给 s1 传递参数@Beanpublic String name() {return "zhangsan";}
}

运行结果如下:

通过结果我们可以看到,已经成功给 name 赋值了。

但是在一个程序中,可能会有多个 name 对象,那么 Spring 会使用哪个对象给 name 赋值呢?

代码如下:

@Component
public class StudentComponent {//    @Bean({"s3", "s4"})@Bean("s3")public Student s1(String name) {return new Student(name, 12);}@Beanpublic Student s2() {return new Student("lisi", 14);}@Beanpublic String name() {return "zhangsan";}
}@Configuration
public class StudentConfiguration {@Beanpublic String name() {return "zhangsan111";}
}

答案是会报错,报错信息如下:

Description:The bean 'name', defined in class path resource [com/gjm/demo/config/StudentConfiguration.class], could not be registered. A bean with that name has already been defined in class path resource [com/gjm/demo/component/StudentComponent.class] and overriding is disabled.

 由于有两个相同i名字的 name 对象,Spring不允许有这种情况出现,就会报错。

那如果将两个 name 方法的名字修改为不同的名字,那么程序是否能成功运行?

代码如下:

@Component
public class StudentComponent {//    @Bean({"s3", "s4"})@Bean("s3")public Student s1(String name) {return new Student(name, 12);}@Beanpublic Student s2() {return new Student("lisi", 14);}//修改名字为 name1@Beanpublic String name1() {return "zhangsan";}
}@Configuration
public class StudentConfiguration {//修改名字为 name2@Beanpublic String name2() {return "zhangsan111";}
}

运行结果如下:

Description:Parameter 0 of method s1 in com.gjm.demo.component.StudentComponent required a single bean, but 2 were found:- name1: defined by method 'name1' in class path resource [com/gjm/demo/component/StudentComponent.class]- name2: defined by method 'name2' in class path resource [com/gjm/demo/config/StudentConfiguration.class]

程序依然会报错,这是因为 Spring 只需要一个 Spring类型的数据,但是我们却提供了两个,那么这时 Spring 就不知道需要使用哪一个了。

关键字:贵州seo排名_深圳工程建设交易服务中心网站_四种基本营销模式_企业培训员工培训平台

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: