别问为啥叫京都大火篇-剑心迷
Spring或许是现在很多人学习的第一个框架(主要我是个碎嘴子,总想扯东扯西)
先对不起各位,我又开始扯皮了。
Spring、SpringMVC、SpringBoot、SpringCloud可以说占了java开发的半壁江山,而学习Spring就成了重中之重,正是Spring这种良好的生态环境,使得程序猿这个物种可以更快的产出馋品锦鲤需要的食物。
Spring是什么?
Spring是一个开源的框架,为了简化企业开发而生,可以使开发变得更加的优雅和简洁
核心本质:–Spring本质就是个IOC和AOP的容器框架。
IOC:控制反转
AOP:面向切面编程
而容器呢,就是管理我们注入到管理应用对象的生命周期,就像一个桶里放的都是存放的对象
Spring的优点
1、Spring通过DI、AOP和消除样板式代码来简化企业级Java开发
2、Spring框架之外还存在一个构建在核心框架之上的庞大生态圈,它将Spring扩展到不同的领域,如Web服务、REST、移动开发以及NoSQL
3、低侵入式设计,代码的污染极低
4、独立于各种应用服务器,基于Spring框架的应用,可以真正实现Write Once,Run Anywhere的承诺
5、Spring的IoC容器降低了业务对象替换的复杂性,提高了组件之间的解耦
6、Spring的AOP支持允许将一些通用任务如安全、事务、日志等进行集中式处理,从而提供了更好的复用
7、Spring的ORM和DAO提供了与第三方持久层框架的的良好整合,并简化了底层的数据库访问
8、Spring的高度开放性,并不强制应用完全依赖于Spring,开发者可自由选用Spring框架的部分或全部
–IOC控制反转(Inversion of Control)
要学会ioc就需要搞清楚4个问题;
1、谁控制谁:在过去编码的过程中,需要什么对象都是自己创建new出来的,由程序员自己来控制对象,但是又了IOC容器之后,变成了由IOC容器来控制对象
2、控制什么:在实现的过程中所需要的对象以及需要依赖的对象
3、什么是反转:在没有IOC容器的时候,是由我们在对象中主动创建依赖的对象,这种是正转。但是有了IOC容器后,依赖的对象由IOC容器创建并注入到了对象之中,由主动创建成了被动的接受,这就是反转
4、哪些方面被反转:需要依赖的对象反转了
DI与IOC
DI是啥:依赖注入(别说,这俩东西就是感觉蛮像的)
很多人把IOC和DI说成一个东西,笼统来说的话是没有问题的,IOC和DI是从不同的角度描述的同一件事,IOC是从容器的角度描述,而DI是从应用程序的角度来描述,也可以这样说,IOC是设计思想,而DI是具体的实现方式
IOC基本的使用与容易忽略(一些功能工作压根用不到)
知识点,拿笔圈起来(下面会进行验证):
1、ApplicationContext就是IOC容器的接口,可以通过此对象获取容器中创建的对象
2、对象在Spring容器创建完成的时候就已经创建完成,不是需要用的时候才创建
3、对象在IOC容器中存储的时候都是单例的,如果需要多例需要修改属性
4、创建对象给属性赋值的时候是通过setter方法实现的
5、对象的属性是由setter/getter方法决定的,而不是定义的成员属性
//创建一个实体类
private String name;
private Integer age;
private String gender;
public Persion(Integer id, String name, Integer age, String gender) {
this.id = id;
this.name = name;
this.age = age;
this.gender = gender;
}
//特意在无参构造添加了一句话来测试spring容器中的对象是合适创建的
public Persion() {
System.out.println("是否创建");
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
<!--给容器中手动注入对象,并且设置值-->
<!--在spring容器中注入对象,测试-->
<bean id="per1" class="com.kaisi.pojo.Persion">
<property name="id" value="1"></property>
<property name="age" value="22"></property>
<property name="name" value="李四"></property>
<property name="gender" value="中"></property>
</bean>
//特意只是加载了配置文件,来验证IOC容器何时创建对象
public class Test {
public static void main(String[] args) {
//解析xml文件对springIOC容器进行测试
ApplicationContext con = new ClassPathXmlApplicationContext("ks.xml");
// Persion per1 = con.getBean("per1", Persion.class);
// System.out.println(per1);
}
}
```![在这里插入图片描述](https://img-blog.csdnimg.cn/20200927200328645.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NTY4NzU0Ng==,size_16,color_FFFFFF,t_70#pic_center)
- **由↑结果就显而易见了,只是加载了容器。对象在IOC容器创建完成的时候就已经创建完成,并不是需要的时候才会创建。*
- 但是注意,这只是默认为单例的时候才这样,如果scope为pretotype,对象不会再容器创建前完成创建,而是调用getBean才会进行创建*
```java
//解析xml文件对springIOC容器进行测试
ApplicationContext con = new ClassPathXmlApplicationContext("ks.xml");
Persion per1 = con.getBean("per1", Persion.class);
Persion per2 = con.getBean("per1", Persion.class);
System.out.println(per1 == per2);
嘿嘿,结果依旧预想效果,因为SpringIOC中默认的 scope=“singleton” 就是单例。当然有默认就可以修改
<!--
bean的作用域:singleton、prototype、request、session
默认情况下是单例的
prototype:多实例的
容器启动的时候不会创建多实例bean,只有在获取对象的时候才会创建该对象
每次创建都是一个新的对象
singleton:默认的单例对象
在容器启动完成之前就已经创建好对象
获取的所有对象都是同一个
request和session是之前版本的,忘记是几了,request是每次请求都是创建一个对象
而session是每次会话创建一个对象
-->
<bean id="per1" class="com.mashibing.bean.Person" scope="prototype"></bean>
将scope属性改为 “prototype” 即可
//解析xml文件对springIOC容器进行测试
ApplicationContext con = new ClassPathXmlApplicationContext("ks.xml");
Persion per1 = con.getBean("per1", Persion.class);
Persion per2 = con.getBean("per1", Persion.class);
System.out.println(per1 == per2);
这一步同时验证了,当作用域为prototype的时候,只有进行调用才会创建对象。一石二鸟。结果false说明对象在内存的地址值并不相同,那么此刻IOC中的对象就不是单例,而是多例
将实例注入到Spring中,不止只有xml文件配置的形式,更方便常用的多基于注解。
如果想要将自定义的bean对象添加到IOC容器中,可以用Spirng提供的注解
Spring中提供了四个主要组件的添加注解:
@Controller:控制器,推荐给controller层添加此注解
@Service:业务逻辑,推荐给业务逻辑层添加此注解
@Repository:仓库管理,推荐给数据访问层添加此注解
@Component:给不属于以上基层的组件添加此注解
值得注意的是:这个四个注解并没有什么区别,都会把自定义的bean注入到Spring容器中,但仿佛约定一般,会给不同的层级加入与之对应的注解,让其他人看起来更加清晰方便。(遇上不按常理出牌的也没办法,认了吧…)
若是使用注解需要注意一些地方
1,当给一个bean对象加入上面任意一个注解
2,此时需要在xml文件中,依赖context命名空间
3,在配置问加入自动扫描的标签,用来告诉Spring需要把哪些类或者方法等等加入到Spring容器中
<context:component-scan base-package=“com.kaisi”></context:component-scan>
-----使用@AutoWired进行自动注入
注意:使用@AutoWried的时候注解的时候,自动装配是根据类型bytype实现的
1、如果根据类型只找到一个,进行直接赋值
2、如果没有找到,直接抛出异常
3、如果找到了多个,那么就会按照注入对象的变量名作为<bean标签>中的id进行匹配
–匹配到直接进行自动注入
–匹配不到继续报异常
//先注入一个
@Service
public class PersonService {
@Autowired
private PersonDao personDao;
public void save(){
System.out.println("p1111");
personDao.save();
}
}
//在注入一个像相同类型的进行测试
@Service
public class PersonService2 extends PersonService{
@Autowired
private PersonDao personDao;
public void save(){
System.out.println("p222");
personDao.save();
}
}
有俩个相同类型的bean注入到IOC容器的时候,就会按照ByName进行匹配。
由↑俩结果可以得出此结论。
还有个有趣的注解是@Qualifier:用此注解可以指定根据name来走哪个方法
1,找到了就直接进行装配注入
2,找不到就直接报错
------自动装配的注解@AutoWired,@Resource
在使用自动装配的时候,出了可以使用@AutoWired注解之外,还可以使用@Resource注解
1、@AutoWired:是spring中提供的注解,@Resource:是jdk中定义的注解,依靠的是java的标准
2、@AutoWired默认是按照类型进行装配,默认情况下要求依赖的对象必须存在,@Resource默认是按照名字进行匹配的,同时可以指定name属性。
注意:@Resource是按照名称进行装配的,如果名字找不到,那么就使用类型
@AutoWired是按照类型进行装配,如果类型找不到那么久使用名字进行查找