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

Spring IOCDI————(1)

1,IOC&DI讲解

1,Spring是啥

Spring就是一个开源框架,他们让我们开发变得更加简单,简单来说,Spring就是一个包含了众多工具方法的IOC容器。那么啥是容器呢,我们之前学习的集合,数据结构那块就是容器,用来存储数据容器,这里也是一样,比如Tomcat就是一个Web容器;

2,啥是IOC

那么什么是IOC呢,我们其实在此之前已经使用过了,大家有没有发现,之前在RequestMapping下的代码是一个对象吧,我们调用它里面的方法实现调用功能,但是有个问题啊,我们从来都没new过对象,是不是,从来都没有,但是我们还是可以调用,这个因为这个RequestController和Controller注解中有IOC注解,就是会把这个类交给Spring管理,交给Spring管理,Spring就会帮我们来实例化对象,就是完全交给Spring;IOC简单来说就是Spring提供的存功能;

IOC带来的好处:
1,资源集中管理:IOC容器会帮我们管理一些资源,比如对象,我们在使用的时候,直接过去取就完了;

2,降低代码耦合度,创建实例的时候不用去关心实例的细节;

3,啥是DI

DI的英文翻译为中文的意思就是依赖注入,这是啥意思呢,刚才说了IOC是存,那么DI就是取,

我们可以通过一些列注解来取到我们需要的Bean,Bean就是对象;

3,Spring,Spring MVC,Spring SpringBoot关系:

三者的关系呢:

1,Spring Boot是基于Spring,Spring Boot是基于Spring框架的封装,简化了配置和部署

2,Spring MVC属于Spring,Spring MVC是Spring的Web模块,Spring Boot默认集成MVC

3,Spring Boot整合Spring全家桶,Spring Boot 可以整合 Spring MVC、Spring Data、Spring Security 等模块。


2,IOC详解

IOC即控制反转,我们想掌握IOC就是掌握IOC容器的创建和Bean的存储;

Bean的存储提供了两类注解:
1,类注解

@Controller,@Service,@Repository,@Component,@Configuration

2,方法注解

@Bean

1,类注解

1,@Controller控制器存储
@Controller
public class UserController {public void sayHello(){System.out.println("Hello,Controller");}
}

使用注解就说明吧这个类给Spring管理了,

@SpringBootApplication
public class JavaTest2025519Application {public static void main(String[] args) {//或缺上下文对象ApplicationContext context = SpringApplication.run(JavaTest2025519Application.class, args);//从上下文中或缺对象UserController userController = context.getBean(UserController.class);//使用对象userController.sayHello();}}

 我们可以直接获得到UserController、大家有没有唤醒一些记忆,这个.class怎么那么熟悉呢,这不反射的类加载嘛~,还有这个上下文,大家从哪听过呢,线程那,大家还有记忆没有,这里的上下文呢,指的是当前的运行环境,可以看做容器,容器存储了很多东西,就是运行环境,

我们看看有没有打印出来:

获取成功了,我们成功获取了一个对象,我们这个对象是根据类型创建的,这里我们还没指定Bean,如果有多个Bean呢,我们可能会在注入的时候进行操作,我们在获取这也能操作,我们还提供了其他的getbean方法,这个ApplicationContext继承了BeanFactory的功能,这里常用的三种方法:

1,getBean(类型)

2,getBean(Sting name)

3,getBean(String name,类型)

来试试:
 

        UserController userController = context.getBean(UserController.class);//使用对象userController.sayHello();UserController userController1 = (UserController) context.getBean("userController");userController1.sayHello();UserController userController2 = context.getBean("userController", UserController.class);userController2.sayHello();

三种方法,打印结果:

这里注意这个String就是以小驼峰命名的类名,如果前两个名字都是大写就不动,就一个大写就改成小驼峰的命名规则,我们还没说多个bean的情况呢,具体体现在哪呢,先提前剧透一下,

我们会使用getBean的(String,类型)来获取到类,String对应的就是bean起的名字,不懂没关系,一会儿会讲解bean;

@Controller
@Data
public class UserController2 {private String name;private Integer age;public void sayHello(){System.out.println("Hello,Controller2");}public void say(){System.out.println(name+age);}@Bean("hei1")public UserController2 hei1(){UserController2 userController2 = new UserController2();userController2.setAge(18);userController2.setName("zhangsan");return userController2;}@Bean("hei2")public UserController2 hei2(){UserController2 userController2 = new UserController2();userController2.setAge(19);userController2.setName("zhangsan");return userController2;}
}
        UserController2 userController3 = context.getBean("hei1", UserController2.class);userController3.say();UserController2 userController4 = context.getBean("hei2", UserController2.class);userController4.say();

看打印结果:

 

所以结论嗷,就是我们给Spring的类,Spring会把每个类都起一个名字,根据名称来获取对应的对象,所以是不能重名的;

我们会根据Spring中的bean来对应对象的,比如我们前三个都是UserController用的是一个类型创获取的三个对象,Spring内部创建的,所以地址应该是想同的,后面两个是UserController2中的两个bean,所以地址应该是不同的,我们来试试:
 

        System.out.println(userController);System.out.println(userController1);System.out.println(userController2);;System.out.println(userController3==userController4);

 

 ok,下面来个面试题,

ApplicationContext和BeanFactory

1,获取Bean是beanFactory提供的功能

2,BeanFactory提供了基础访问容器的功能,ApplicationContext是BeanFactory的子类,继承了BeanFactory之外还提供了国际化支持,资源访问支持,事件传播支持,

3,从性能方面,Application更高效,会一次加载并初始化所有的Bean,而BeanFactoty是需要哪个才加载哪个,更加轻量化,有点像单例模式的懒汉和饿汉模式;

2,@Service(服务存储)
@Service
public class UserService {public void sayHello(){System.out.println("Hello,I'm Service");}
}
        UserService userService = context.getBean(UserService.class);userService.sayHello();

 

3,@Repository(仓库存储)
@Repository
public class UserRepository {public void sayHello(){System.out.println("Hello,I'm Repository");}
}
        UserRepository userRepository = context.getBean(UserRepository.class);userRepository.sayHello();

 

4,@Component(组件存储)
@Component
public class UserComponent {public void sayHello(){System.out.println("Hello,I'm Component");}
}
        UserComponent userComponent = context.getBean(UserComponent.class);userComponent.sayHello();

 

5,@Configuration(配置存储)
@Configuration
public class UserConfiguration {public void sayHello(){System.out.println("Hello,I'm Configuration");}
}
        UserConfiguration userConfiguration = context.getBean(UserConfiguration.class);userConfiguration.sayHello();

 

2,为啥要这么多类注解

整这么多注解嘎哈呀,其实他们没有太大区别的,除了@Controller,@Controller可以返回视图大家还记得不,其他的就在语义上有区别,我们是可以进行替换的,但是还是推荐按标准来;这些注解都是@Component的子类;

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

@Servie:业务逻辑层,处理具体的业务逻辑.

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

@Configuration:配置层.处理项⽬中的⼀些配置信息.

3,方法注解

类注解是写在类上的,但是嗷,存在两个问题

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

2,一个类,有多个对象

1,定义一个对象
@Data
public class User {private String name;private Integer age;
}

先来一个User,

@Component
public class UserController3 {@Beanpublic User get(){User user = new User();user.setName("yaoyu");user.setAge(78);return user;}
}

新的控制器,我们想拿到这个User,直接获取想要的对象

        User user = context.getBean(User.class);System.out.println(user);

 

2,定义多个对象
@Component
public class UserController3 {@Beanpublic User get(){User user = new User();user.setName("yaoyu");user.setAge(78);return user;}@Beanpublic User get2(){User user = new User();user.setName("张三");user.setAge(18);return user;}
}

那么接下来如何应对呢,我们后面注入的时候有更好的方法,现在我们可以通过GetBean方法来输入方法名来区分比如get和get2,

        User user1 = context.getBean("get",User.class);System.out.println(user1);User user2 = context.getBean("get2",User.class);System.out.println(user2);

 

3,重命名Bean

我们还可以给Bean起名字:

    @Bean("h1")public User get3(){User user = new User();user.setName("yaoyu21212");user.setAge(78123123);return user;}@Bean("h2")public User get4(){User user = new User();user.setName("张三123");user.setAge(18123123);return user;

 

        User user3 = context.getBean("h1",User.class);System.out.println(user3);User user4 = context.getBean("get3",User.class);System.out.println(user4);

我们看看这个是我们起的名字生效呢,还方法名生效呢, 没有类名为get3,看来还是自定义的名的优先级比较高一点;

        User user3 = context.getBean("h1",User.class);System.out.println(user3);User user5 = context.getBean("h2",User.class);System.out.println(user5);

 

 这下Bean就讲解完了;

4,扫描路径

我们的默认扫描路径就是Application同级以及以下的路径为扫描路径,我们也是可以修改的,使用@ComponentScan({"com.example.demo"})注解,里面是修改的路径,这么说的话如果被那5个类注解修饰的Bean注解也是不一定完全生效的,这是因为可能没配置扫描路径,如果在扫描路径外,那就白忙活了;


3,DI详解

相关文章:

  • 10.14 Function Calling与Tool Calling终极解析:大模型工具调用的5大核心差异与实战优化
  • 40亿非负整数中找到出现两次的数和所有数的中位数
  • 视觉-和-语言导航的综述:任务、方法和未来方向
  • 20. 自动化测试框架开发之Excel配置文件的IO开发
  • 雷电模拟器安装 KitsuneMagisk (原 Magisk-delta)
  • 当多云管理陷入泥潭,一体化平台如何破局?
  • PCB设计如何用电源去耦电容改善高速信号质量
  • 32、跨平台咒语—— React Native初探
  • leetcode3371. 识别数组中的最大异常值-medium
  • 扫描网络内所有设备的IP地址
  • linux kernel 编译
  • ONIE安装NOS操作说明
  • 5.19 打卡
  • 【C#】用 DevExpress 创建带“下拉子表”的参数表格视图
  • 利用SAMap整合跨物种单细胞/空间转录组数据
  • 简单光学成像技术及其研究进展
  • 用户行为日志分析的常用架构
  • 【Pandas】pandas DataFrame mode
  • 《打造第二大脑》
  • 代购商城系统可以解决哪些重点难题?
  • 多家国有大行存款利率即将迎来新一轮下调
  • 家国万里·时光故事会|科学家伉俪,用玉米书写家国情怀
  • 陕西:未来一周高温持续,继续发布冬小麦干热风风险预警
  • 词条数量大幅扩充,《辞海》第八版启动编纂
  • “朱雀玄武敕令”改名“周乔治华盛顿”?警方称未通过审核
  • 科普|男性这个器官晚到岗,可能影响生育能力