当前位置: 首页 > news >正文

音乐网站开发环境描述要建设一个网站需要准备些什么

音乐网站开发环境描述,要建设一个网站需要准备些什么,河南省建设工程注册中心网站,h5旅游网站开发通过前一篇文章,我们已经知道了Spring IoC和DI的基本概念,这篇文章我们将系统地学习Spring-IoC和DI的操作。前面我们提到的IoC控制反转,就是将对象的控制权交给Spring的IoC容器,由IoC容器创建及管理对象。也就是bean(S…

通过前一篇文章,我们已经知道了Spring IoC和DI的基本概念,这篇文章我们将系统地学习Spring-IoC和DI的操作。

前面我们提到的IoC控制反转,就是将对象的控制权交给Spring的IoC容器,由IoC容器创建及管理对象。也就是bean(Spring管理的对象统称为“bean”)的存储。

IoC详解

Bean的存储

将对象存储在Spring中共有两种注解类型可以实现:

1、类注解:@Controller、@Service、@Repository、@Component、@Configuration

2、方法注解:@Bean

@Controller(控制器存储)

如图,在启动类中创建一个子目录Controller:

类中代码如下:

@Controller
public class HelloController {public void sayHi(){System.out.println("hello Controller……");}
}

如何知道当前对象已经存在Spring容器中了呢?

接下来我们学习如何从Spring容器中获取对象。

点进Spring的启动类中,添加上如下代码:

@SpringBootApplication
public class SpringIoCApplication {public static void main(String[] args) {//获取Spring上下文对象ConfigurableApplicationContext run = SpringApplication.run(SpringIoCApplication.class, args);//从Spring上下文中获取对象HelloController bean = run.getBean(HelloController.class);//使用对象bean.sayHi();}}

观察运行结果,发现成功获取到了Controller对象,并执行了sayHi()方法:把@Controller删去重新执行一遍代码:

将错误信息翻译一下:Spring容器中没有找到这个Bean。

获取Bean的其他方式

上述代码是根据类型来查找对象,如果Spring容器中,同一类型存在多个bean的话,怎么来获取呢?

ApplicationContext也提供了其他获取bean的方式,ApplicationContext获取bean对象的功能,是父类BeanFactory提供的功能。

观察getBean方法的源码:

常用的是上述1,2,4种,这三种方式,获取到的bean是一样的(单例模式)。

其中1,2种都涉及到根据名称来获取对象。bean的名称是什么呢? 

刚才我们讲了bean是spring框架在运行时管理的对象,Spring会给管理的对象起一个名字,就是bean的名称,bean的名称在Spring中是唯一的,类似于学生的学号或者人的身份证号。

Bean的命名约定

默认情况下,首字母小写的驼峰表示(如:我们刚才写的HelloController,Bean的名称为:helloController)。特殊情况下,如果前两个字母均为大写,Bean的名称就是原来的类名(如:UController,Bean的名称是UController)。 


根据这个命名规则,我们来获取Bean:

    //获取Spring上下文对象ConfigurableApplicationContext run = SpringApplication.run(SpringIoCApplication.class, args);//根据Bean的名称获取BeanHelloController helloController = (HelloController) run.getBean("helloController");//根据Bean的名称和类型获取BeanHelloController bean = run.getBean("helloController", HelloController.class);//根据Bean的类型获取BeanHelloController bean1 = run.getBean(HelloController.class);System.out.println(helloController);System.out.println(bean1);System.out.println(bean);

运行结果:

地址一样,说明对象是同一个。

常见面试题:ApplicationContext VS BeanFactory 

1、关系上,他们是父子关系,BeanFactory的功能ApplicationContext都有。除此之外,ApplicationContext还具备环境、资源管理等功能。

2、性能上

Beanfactory是懒加载(什么时候使用什么时候加载),ApplicationContext是提前加载(一开始就把全部对象加载完了)。

@Service(服务存储)

Service类代码:

@Service
public class UserService {public void sayHi(){System.out.println("hello service");}
}

获取Bean的代码 

    //获取Spring上下文对象ConfigurableApplicationContext run = SpringApplication.run(SpringIoCApplication.class, args);UserService bean = run.getBean(UserService.class);bean.sayHi();

运行结果: 

 @Repository(仓库存储)

Repository类:

@Repository
public class UserRepository {public void sayHi(){System.out.println("hello Repository");}
}

获取Bean的代码: 

//获取Spring上下文对象ConfigurableApplicationContext run = SpringApplication.run(SpringIoCApplication.class, args);UserRepository bean = run.getBean(UserRepository.class);bean.sayHi();

运行结果:

@Component(组件存储)

Component类:

@Component
public class UserComponent {public void sayHi(){System.out.println("hello Component");}
}

获取Bean: 

    //获取Spring上下文对象ConfigurableApplicationContext run = SpringApplication.run(SpringIoCApplication.class, args);UserComponent bean = run.getBean(UserComponent.class);bean.sayHi();

运行结果:

 @Configuration(配置存储)

Configuration类:

@Configuration
public class UserConfig {public void sayHi(){System.out.println("hello configuration");}
}

获取Bean :

 //获取Spring上下文对象ConfigurableApplicationContext run = SpringApplication.run(SpringIoCApplication.class, args);UserConfig bean = run.getBean(UserConfig.class);bean.sayHi();

运行结果:

为什么要有那么多的类注解?

这与我们前面提到的应用分层是呼应的。让程序员看到类注解之后,就能直接了解当前类的用途。

@Controller:控制层,接收请求,对请求进行处理,并进行响应。

@Service:业务逻辑层,处理具体的业务逻辑。

@Reposity:数据访问层,也称为持久层,负责数据访问操作。

@Configuration:配置层,处理项目中的一些配置信息。

调用流程如下:

查看这些注解的源码: 可以发现它们里面都有一个相同的@Component(元注解)注解,说明它们都是@Component的“子类”。

“@Controller”,@Service和@Repository用于更具体的用例(分别在控制层,业务逻辑层,持久化层)。

方法注解@Bean

类注解是添加到某个类上的,但是存在两个问题:

1、使用外部包里的类,没办法添加类注解。

2、一个类需要多个对象比如多个数据源。

这种情况我们就需要使用方法注解@Bean。

我们先来看看方法注解如何使用:

先创建一个外部包类UserInfo:

@Data
public class UserInfo {private String name;private Integer age;private Integer id;public UserInfo(){}public UserInfo(String name) {this.name = name;}
}

 使用@Bean注解:

public class BeanConfig {@Beanpublic UserInfo userInfo(){return new UserInfo("zhangsan");}
}

获取Bean:

   ConfigurableApplicationContext run = SpringApplication.run(SpringIoCApplication.class, args);UserInfo bean = run.getBean(UserInfo.class);System.out.println(bean)

将代码写入后发现执行结果如下 :

找不到Bean,这是为什么呢?

在Spring框架的涉及中,方法注解@Bean要配合类注解才能将对象正常存储到Spring容器中。

修改代码如下: 

@Configuration
public class BeanConfig {@Beanpublic UserInfo userInfo(){return new UserInfo("zhangsan");}
}

定义多个对象

对于同一个类如何定义多个对象呢?

修改@Bean类如下:

@Configuration
public class BeanConfig {@Beanpublic UserInfo userInfo(){return new UserInfo("zhangsan");}@Beanpublic UserInfo userInfo1(){return new UserInfo("lisi");}@Beanpublic UserInfo userInfo2(){return new UserInfo("wangwu");}
}

如果我们此时通过类型获取对象,获取的是哪个对象呢? 

//获取Spring上下文对象ConfigurableApplicationContext run = SpringApplication.run(SpringIoCApplication.class, args);UserInfo bean = run.getBean(UserInfo.class);System.out.println(bean);

运行结果:报错信息显示:期望只有一个匹配,但是根据这个类型找到了3个Bean,userInfo,userInfo1,userInfo2。

接下来我们可以通过Bean的名称来获取Bean,我们刚才讲了类注解的Bean的名称,那方法注解Bean的名称又是什么呢?

其实就是——方法名。

代码如下:

         //获取Spring上下文对象ConfigurableApplicationContext run = SpringApplication.run(SpringIoCApplication.class, args);UserInfo bean = (UserInfo) run.getBean("userInfo");System.out.println(bean);UserInfo bean1 = (UserInfo) run.getBean("userInfo1");System.out.println(bean1);UserInfo bean2 = (UserInfo) run.getBean("userInfo2");System.out.println(bean2);

运行结果:

Bean的名称总结 

1、五大注解:

类名:首字母小写

        如果类名前两位为大写,bean的名称为类名本身

2、@Bean

bean 名称:方法名

扫描路径

使用前面学习的注解声明的bean,一定会生效吗?

不一定(原因:bean想要生效,还需要被Spring扫描)

将启动类放到Controller目录下: 写上如下代码:

   //获取Spring上下文对象ConfigurableApplicationContext run = SpringApplication.run(SpringIoCApplication.class, args);HelloController bean1 = run.getBean(HelloController.class);bean1.sayHi();UserService bean = run.getBean(UserService.class);bean.sayHi();

运行结果:可以看到HelloController的bean对象能够正常获取并使用,而UserService的bean对象却显示没有找到。

这是为什么呢?

Spring的默认扫描路径是当前目录和当前目录下的子目录。我们可以通过@ComponentScan来配置扫描路径。

修改代码如下:

@ComponentScan("com.example.springioc")
@SpringBootApplication
public class SpringIoCApplication {public static void main(String[] args) {//获取Spring上下文对象ConfigurableApplicationContext run = SpringApplication.run(SpringIoCApplication.class, args);HelloController bean1 = run.getBean(HelloController.class);bean1.sayHi();UserService bean = run.getBean(UserService.class);bean.sayHi();}
}

运行结果:

推荐做法:

把启动类放在我们希望扫描的包的路径下,这样我们定义的bean就都可以被扫描到。

DI详解

上面我们讲解了控制反转IoC的细节,接下来,我们学习依赖注入DI的细节。

依赖注入是一个过程,是指IoC容器在创建Bean时,去提供运行时所依赖的资源,而资源指的就是对象。

关于依赖注入,Spring也给我们提供了三种方式:

1、属性注入

2、构造方法注入

3、Setter注入

属性注入

属性注入需要使用@Autowired这个注解。

例如:在HelloController类中注入UserSeverice对象。

HelloController类代码如下:

@Controller
public class HelloController {@Autowiredprivate UserService userService;public void sayHi(){userService.sayHi();System.out.println("hello Controller……");}
}

 获取Bean并调用sayHi方法:

//获取Spring上下文对象ConfigurableApplicationContext run = SpringApplication.run(SpringIoCApplication.class, args);HelloController bean1 = run.getBean(HelloController.class);bean1.sayHi()

执行结果:

去掉 @Autowired,重新执行:

出现空指针异常。

构造方法注入 

HelloController代码:


@Controller
public class HelloController {private UserService userService;public HelloController(UserService userService) {this.userService = userService;}public void sayHi(){userService.sayHi();System.out.println("hello Controller……");}
}

获取使用Bean代码 :

    //获取Spring上下文对象ConfigurableApplicationContext run = SpringApplication.run(SpringIoCApplication.class, args);HelloController bean1 = run.getBean(HelloController.class);bean1.sayHi()

执行结果: 那如果我给HelloController再加上一个无参构造方法呢?

代码修改如下:

@Controller
public class HelloController {private UserService userService;public HelloController() {}public HelloController(UserService userService) {this.userService = userService;}public void sayHi(){userService.sayHi();System.out.println("hello Controller……");}
}

可以看到报了一个空指针异常,这是因为Spring会默认使用无参的构造方法,这就导致了userService是一个空对象 。

解决办法:

为构造方法添加@Autowired注解:

@Controller
public class HelloController {private UserService userService;public HelloController() {}
@Autowiredpublic HelloController(UserService userService) {this.userService = userService;}public void sayHi(){userService.sayHi();System.out.println("hello Controller……");}
}

那么如果我注入两个对象,并且加入带一个参数的构造方法和带两个参数的构造方法(不加注解的情况)呢?

代码如下:

@Controller
public class HelloController {private UserService userService;private UserRepository userRepository;public HelloController(UserService userService) {this.userService = userService;}public HelloController(UserService userService, UserRepository userRepository) {this.userService = userService;this.userRepository = userRepository;}public void sayHi(){userRepository.sayHi();userService.sayHi();System.out.println("hello Controller……");}
}

 获取使用Bean:

    //获取Spring上下文对象ConfigurableApplicationContext run = SpringApplication.run(SpringIoCApplication.class, args);HelloController bean1 = run.getBean(HelloController.class);bean1.sayHi()

执行结果: 

翻译一下这两个错误日志:构造方法有两个,我不知道应该使用哪个构造方法(没有默认构造方法)。

我们为两个参数的构造方法添加上@Autowired注解:

@Controller
public class HelloController {private UserService userService;private UserRepository userRepository;public HelloController(UserService userService) {this.userService = userService;}@Autowiredpublic HelloController(UserService userService, UserRepository userRepository) {this.userService = userService;this.userRepository = userRepository;}public void sayHi(){userRepository.sayHi();userService.sayHi();System.out.println("hello Controller……");}
}

代码成功执行:

总结:

构造函数注入

1、只有一个构造函数的情况,不需要加@Autowired

2、如果有多个构造函数,需要指定默认的构造函数(通过@Autowired指定,如果未指定,默认使用无参的构造函数

构造函数规范

1、如果添加构造函数,把无参构造函数显示添加

依赖注入:

添加构造函数时,使用@Autowired告知Spring要使用的构造函数。 

 Setter方法注入

Setter方法注入和属性注入一样需要添加@Autowired注解,否则会报空指针异常

@Controller
public class HelloController {private UserService userService;@Autowiredpublic void setUserService(UserService userService) {this.userService = userService;}public void sayHi(){userService.sayHi();System.out.println("hello Controller……");}
}

 获取使用Bean:

    //获取Spring上下文对象ConfigurableApplicationContext run = SpringApplication.run(SpringIoCApplication.class, args);HelloController bean1 = run.getBean(HelloController.class);bean1.sayHi()

执行结果:

三种注入方式优缺点分析(八股文): 

@Autowired存在问题

当同一类型存在多个bean时,使用@Autowired会存在问题。

刚才的Beanconfig类中就存在多个bean:

@Configuration
public class BeanConfig {@Beanpublic UserInfo userInfo(){return new UserInfo("zhangsan");}@Beanpublic UserInfo userInfo1(){return new UserInfo("lisi");}@Beanpublic UserInfo userInfo2(){return new UserInfo("wangwu");}
}

同样将它注入HelloController类中: 

@Controller
public class HelloController {@Autowiredprivate UserInfo userInfo;public void sayHi(){System.out.println(userInfo);System.out.println("hello Controller……");}
}

获取Bean:

    //获取Spring上下文对象ConfigurableApplicationContext run = SpringApplication.run(SpringIoCApplication.class, args);HelloController bean1 = run.getBean(HelloController.class);bean1.sayHi()

可以看到,此时是能正常运行的: 但是倘若我给要注入的对象换个名字:

@Controller
public class HelloController {@Autowiredprivate UserInfo user;public void sayHi(){System.out.println(user);System.out.println("hello Controller……");}
}

执行结果: 

报错原因:非唯一的Bean对象。

如何解决上述问题呢?Spring提供了三种解决方案:

  • @Primary
  • @Qualifier
  • @Resource

使用@Primary注解:当存在多个相同类型的Bean注入时,加上@Primary注解,来确定默认的实现。

代码如下:

@Configuration
public class BeanConfig {@Primary//指定该Bean未默认Bean的实现@Beanpublic UserInfo userInfo(){return new UserInfo("zhangsan");}@Beanpublic UserInfo userInfo1(){return new UserInfo("lisi");}@Beanpublic UserInfo userInfo2(){return new UserInfo("wangwu");}
}

重新执行 :

使用@Qualifier注解:指定当前要注入的bean对象。在@Qualifier的value属性中,指定注入的bean的名称。(@Qualifiler注解不能单独使用,必须配合@Autowired使用)。

HelloController代码如下:

@Controller
public class HelloController {@Qualifier("userInfo1")@Autowiredprivate UserInfo user;public void sayHi(){System.out.println(user);System.out.println("hello Controller……");}
}

执行结果:

使用@Resource注解:是按照bean的名称进行注入。通过name属性指定要注入的bean的名称。

代码如下: 

@Controller
public class HelloController {@Resource(name = "userInfo2")private UserInfo user;public void sayHi(){System.out.println(user);System.out.println("hello Controller……");}
}

结果:

常见面试题:@Autowired VS @Resource的区别

@Autowired是spring框架提供的注释,而@Resource是JDK提供的注释。

@Autowired默认按照类型注入,而@Resource是按照名称注入,相比于@Autowired来说,@Resource支持更多参数设置,例如name设置,根据名称获取Bean

http://www.dtcms.com/a/415259.html

相关文章:

  • display ip interface brief 概念及题目
  • asp网站整站下载器网站建设入什么科目
  • 网站建设国内排行如何做网站 知乎
  • 网站关于 模板三亚网站优化
  • Nginx部署vue以及转发配置记录
  • Elasticsearch - 分布式搜索与分析引擎
  • 网站开发者模式下载视频设计网站做多大合适
  • wordpress建企业商城南宁网站的优化
  • 通才机器人策略中的捷径学习:数据集多样性和碎片化的作用
  • 【轮播图】HTML+CSS+JavaScript实现轮播图
  • Low-Overhead Sensing RS Design for Integrated Sensing and Communication (ISAC)
  • 如何快速收录一个网站的信息网页设计与制作作业成品免费
  • MyEclipse在高分辨率显示屏上图标显示太小的解决方案
  • 网站 多语言处理wordpress搜索表单
  • Python 2025:物联网与边缘计算的智能融合新纪元
  • 小迪安全v2023学习笔记(九十讲)—— 小程序篇反编译外在主包分包配置泄露算法逆向未授权
  • 机器学习模型中异常样本、特征的三种常见分类与鉴别方法
  • 有口碑的常州网站建设建设网银怎么提高转账限额
  • 湖南响应式网站哪里有58同城怎么发布信息
  • 《前端开发中常用的快捷键大全》
  • 跳舞游戏做的广告视频网站平度建设局网站
  • 众筹网站建设公司金蝶官网首页
  • 智能汽车安全基石:通过CAS密钥管理系统实现全周期密钥管理与固件签名
  • 基于Python CNN推荐的电影资讯App软件的设计与实现
  • 如何识别网站的建站程序做网站的客户多吗
  • 找人做网站推广wordpress二次开发手册chm
  • 如何降低重复率?卷卷降AI
  • 建网站哪家好新闻wordpress 修改404
  • 基于微信小程序的智能在线预约挂号系统【2026最新】
  • 网站域名管理怎么登陆深圳服务网站建设