Spring笔记(更新ing)

1、Spring

1.1、简介

  • Spring:春天 ----->给软件行业带来了春天

  • 2002,首次推出了Spring框架的雏形:interface21框架

  • Spring框架即以interface21框架为基础,经过重新设计,并不断丰富其内涵,于2004年3月24日,发布了1.0正式版。

  • Rod Johnson,Spring Framework创始人,著名作者。悉尼大学的音乐学博士。

  • spring理念:使现有的技术更加容易使用,本身是一个大杂烩,整合了现有的技术框架

  • SSH : Struct2 + Spring + Hibernate

  • SSM:SpringMVC + Spring + Mybatis

官网:Spring Framework

官方下载地址:JFrog

Github: GitHub - spring-projects/spring-framework: Spring Framework

 <!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
 <dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-web</artifactId>
     <version>5.2.0.RELEASE</version>
 </dependency>
 ​
 <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
 <dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-jdbc</artifactId>
     <version>5.2.0.RELEASE</version>
 </dependency>

1.2、优点

  • Spring是一个开源的免费的框架(容器)

  • Spring是一个轻量级的、非入侵式的框架

  • 控制反转(IOC),面向切面编程(AOP)

  • 支持事务的处理,对框架整合的支持

总结一句话:Spring就是一个轻量级的控制反转(IOC)和面向切面编程(AOP)的框架

1.3、组成

 

1.4、拓展

  • Spring Boot

    • 一个快速开发的脚手架

    • 基于SpringBoot可以快速的开发单个微服务

    • 约定大于配置

  • Spring Cloud

    • SpringCloud是基于SpringBoot实现的

因为现在大多数的公司都在使用SpringBoot进行快速开发、学习SpringBoot的前提,需要完全掌握Spring及SpringMVC

承上启下的作用

2、 IOC理论推导

下面是没有用到 IOC容器之前,我们原始的方式:

  1. UserDao 接口类

     public interface UserDao {
         
         public void getUser();
         
     }

  2. UserDaoImpl实现类

     public class UserDaoImpl implements UserDao {
         
         @Override
         public void getUser(){
             
             System.out.println("获取用户数据!");
             
         }
         
     }

  3. UserService 业务接口

     public interface UserService {
         
         public void getUser();
         
     }

  4. UserServiceImpl 业务实现类

     public class UserServiceImpl implements UserService {
         
         private UserDao = new UserDaoImpl();
         
         @Override
         public void getUser() {
             
             userDao.getUser();
             
         }
         
     }
  5. 测试类

 @Test
 public void test() {
     
     UserService service = new UserServiceImpl();
     service.getUser();
     
 }

在外面之前的业务中,用户的需求可能会影响我们原来的代码,我们需要根据用户的需求去修改源代码。如果程序代码量十分大,

修改一次的成本代价十分昂贵!

现在我们来修改一下代码,来体会一下解耦合的操作:

  • 我们使用一个Set接口实现

     public class UserServiceImpl implements UserService {
         
         private UserDao userDao;
     ​
         //利用set进行动态实现值的注入
         public void setUserDao(UserDao userDao) {
             this.userDao = userDao;
         }
         
         @Override
         public void getUser() {
             
             userDao.getUser();
             
         }
         
     }
     ​
  • 测试类中的修改

 @Test
 public void test () {
     
     UserServiceImpl service = new UserServiceImpl();
     service.setUserDao(new UserDaoMySqlImpl());
     service.getUser();
     
     service.setUserDao(new UserDaoOracleImpl());
     service.getUser();
     
 }

思考:

我们原始的方法和上面的方法已经发生了根本性的变化:

  • 之前,所有东西都是由程序主动创建对象,控制权在程序员手上

  • 现在,使用了set注入之后,程序不再具有主动性,而是变成了被动的接受对象,把主动权交给了调用者

这种思想,从本质上解决了问题,我们程序员不用再去管理对象的创建了。系统的耦合性大大降低,可以更加专注的在业务的实现上!

这就是IOC的原型。

3、IOC本质

控制反转IOC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IOC的一种方法,也有人认为DI只是IOC的另一种说法。

没有IOC的程序中,我们使用面向对象编程,对象的创建与对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,

控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。

 

IOC是Spring框架的核心内容,使用多种方式完美的实现了IOC,可以使用XML配置,也可以使用注解,新版本的Spring也可以零配置实现IOC。

Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用时再从IOC容器中取出需要的对象。

 

采用XML方式配置Bean的时候,Bean的定义信息和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在

实体类中,从而达到了零配置的目的。

控制反转是一种通过描述(xml或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IOC容器,其实现方法是依赖注入

(Dependency Injection,DI)。

4、编写第一个Spring代码(Hello Spring)

  1. 编写一个Hello实体类

     public class Hello {
         
         private String name;
         
         public String getName() {
             return name;
         }
         
         public void setName(String name) {
             this.name = name;        
         }
         
         public void show() {
            System.out.println("Hello" + name); 
         }
         
     }
     ​

  2. 编写我们的Spring文件,命名为beans.xml

 <?xml version="1.0" encoding="UTF-8"?>
 <beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans.xsd">
     
     <!--bean就是java对象,由Spring创建和管理-->
     <bean id = "hello" class = "com.shelby.pojo.Hello">
         <property name = "name" value = "Spring" />
     </bean>
     
 </beans>

  1. 测试类

     @Test
     public void test() {
         
         //解析beans.xml文件,生成管理相应的Bean对象。
         ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
         //getBean :参数即为Spring配置文件中的bean的id。
         Hello hello = context.getBean("hello")
         hello.show();
         
     }

这个过程就叫控制反转:

控制:谁来控制对象的创建,传统应用程序的对象是由程序本身控制创建的,使用Spring后,对象是由Spring来创建的。

反转:程序本身不创建对象,而变成被动的接受对象。

依赖注入:就是利用set方法进行注入的。

IOC是一种编程思想,由主动的编程变成被动的接受

可以通过new ClassPathXmlApplicationContext去浏览一下底层源码。

到了现在,我们彻底不用再程序中改动了,要实现不同的操作,只需要在xml配置文件中进行修改。

所谓的IOC,一句话搞定:对象由Spring来创建,管理,装配

5、IOC创建对象的方式

  1. 使用无参构造创建对象 【默认】

  2. 使用有参构造创建对象

    1. 下标赋值

     <bean id="user" class="com.shelby.pojo.user">
         <constructor-arg index="0" value="小傻子学java" />
     </bean>
    1. 类型 【不建议使用】

       <bean id="user" class="com.shelby.pojo.user">
           <constructor-arg type="java.lang.String" value="小傻子学java" />
       </bean>
    2. 参数名

       <bean id="user" class="com.shelby.pojo.user">
           <constructor-arg name="name" value="小傻子学java" />
       </bean>

总结:在配置文件加载的时候,容器中管理的对象就已经初始化了!

6、Spring配置

6.1、别名

  • 如果添加了别名,我们也可以使用别名获取到这个对象

 <alias name="user" alias="userNew" />

6.2Bean的配置

  • id :bean的唯一标识符,也就是相当于我们学的对象名

  • class :bean对象所对应的全限定名:包名 + 类型

  • name :也是别名,name可以取多个别名(比alias高级)

 <bean id="user" class="com.shelby.pojo.user" name="userNew" />

6.3、import

  • import,一般用于团队开发使用,可以将多个配置文件,导入合并为一个

    • applicationContext.xml

 <import resource="xxx.xml"/>

使用的时候,直接使用总的配置就可以了。

7、依赖注入

7.1、构造器注入

【见第五章-第2点】

7.2、Set方式注入 【重点】

  • 依赖注入:Set注入

    • 依赖:bean对象的创建依赖于容器

    • 注入:bean对象中的所有属性,由容器来注入!

【模拟Demo】

  1. 复杂类型

 //定义一个Address的实体类
 package com.shelby.pojo;
 ​
 public class Address {
     
     private String addr;
 ​
     public String getAddr() {
         return addr;
     }
 ​
     public void setAddr(String addr) {
         this.addr = addr;
     }
 }

  1. 真实测试对象

 //定义一个Student的实体类
 package com.shelby.pojo;
 ​
 import java.util.*;
 ​
 public class Student {
 ​
     private String name;
     private Address addr;
     private String[] books;
     private List<String> hobbies;
     private Map<String, String> card;
     private Set<String> games;
     private String wife;
     private Properties info;
 ​
     public String getName() {
         return name;
     }
 ​
     public void setName(String name) {
         this.name = name;
     }
 ​
     public Address getAddr() {
         return addr;
     }
 ​
     public void setAddr(Address addr) {
         this.addr = addr;
     }
 ​
     public String[] getBooks() {
         return books;
     }
 ​
     public void setBooks(String[] books) {
         this.books = books;
     }
 ​
     public List<String> getHobbies() {
         return hobbies;
     }
 ​
     public void setHobbies(List<String> hobbies) {
         this.hobbies = hobbies;
     }
 ​
     public Map<String, String> getCard() {
         return card;
     }
 ​
     public void setCard(Map<String, String> card) {
         this.card = card;
     }
 ​
     public Set<String> getGames() {
         return games;
     }
 ​
     public void setGames(Set<String> games) {
         this.games = games;
     }
 ​
     public String getWife() {
         return wife;
     }
 ​
     public void setWife(String wife) {
         this.wife = wife;
     }
 ​
     public Properties getInfo() {
         return info;
     }
 ​
     public void setInfo(Properties info) {
         this.info = info;
     }
 ​
     @Override
     public String toString() {
         return "Student{" +
                 "name='" + name + '\'' +
                 ", addr=" + addr +
                 ", books=" + Arrays.toString(books) +
                 ", hobbies=" + hobbies +
                 ", card=" + card +
                 ", games=" + games +
                 ", wife='" + wife + '\'' +
                 ", info=" + info +
                 '}';
     }
 }
 ​
 ​

3.applicationContext.xml配置文件

 <?xml version="1.0" encoding="UTF-8"?>
 <beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://www.springframework.org/schema/beans
         https://www.springframework.org/schema/beans/spring-beans.xsd">
 ​
     <bean id="address" class="com.shelby.pojo.Address"  >
         <property name="address" value="上海"/>
     </bean>
     
     <!--普通值注入,直接使用value-->
     <bean id="student" class="com.shelby.pojo.Student">  
         <property name="name" value="小傻子学java"/>
         
     <!--Bean注入,使用ref-->
         <property name="address" ref="address"/>
         
     <!--数组注入-->
         <property name="books">
             <array>
                 <value>红楼梦</value>
                 <value>三国演义</value>
             </array>
         </property>
         
     <!--List注入-->
         <property name="hobbies">
             <list>
                 <value>写代码</value>
                 <value>唱歌</value>
             </list>
         </property>
         
     <!--Map注入-->
         <property name="card">
             <map>
                 <entry key="身份证" value="333333222222221111"/>
             </map>
         </property>
         
     <!--Set注入-->
         <property name="games">
             <set>
                 <value>LOL</value>
                 <value>COC</value>
             </set>
         </property>
         
     <!--null注入-->
         <!--<property name="wife" value="">-->
         <property name="wife">
             <null/>
         </property>
         
     <!--Properties注入-->
         <property name="info">
             <props>
                 <prop key="学号">1001</prop>
                 <prop key="性别">男</prop>
             </props>
         </property>
     </bean> 
 </beans>

4.测试类

 //测试类
 @Test
 public void test(){
     
     ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
     Student stu = (Student)context.getBean("student");
     System.out.println(stu.toStirng());
     
 }

7.3、拓展方式注入

  1. p(property)命名空间注入,可以直接使用p:属性名来注入属性的值

 <?xml version="1.0" encoding="UTF-8"?>
 <beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:p="http://www.springframework.org/schema/p"
     xsi:schemaLocation="http://www.springframework.org/schema/beans
         https://www.springframework.org/schema/beans/spring-beans.xsd">
 ​
     <bean id="student" class="cm.shelby.pojo.Student" p:name="小傻子学java"/>
 ​
 </beans>
  1. c(constructor-args)命名空间注入,通过构造器注入

  • 使用c命名空间注入,需要有有参构造器

 <?xml version="1.0" encoding="UTF-8"?>
 <beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:p="http://www.springframework.org/schema/c"
     xsi:schemaLocation="http://www.springframework.org/schema/beans
         https://www.springframework.org/schema/beans/spring-beans.xsd">
 ​
     <bean id="student" class="cm.shelby.pojo.Student" c:name="小傻子学java"/>
 ​
 </beans>

注意点:使用p命名空间和c命名空间需要导入相应的约束!

7.4bean的作用域

 

  1. 单例模式【Spring默认机制】

 

 <bean id="student" class="cm.shelby.pojo.Student" p:name="小傻子学java" scope="singleton"/>
  1. 原型模式:每次从容器中getBean()的时候,都会产生一个新对象

 

 <bean id="student" class="cm.shelby.pojo.Student" p:name="小傻子学java" scope="prototype"/>
  1. 其余的request、session、application这三个只能在web开发中使用到。

8、Bean的自动装配

  • 自动装配是Spring满足bean依赖的一种方式

  • Spring会在上下文中自当寻找,并自动给bean装配属性

在Spring中有三种装配方式

  1. 在xml中显示的配置

  2. 在java中显示的配置

  3. 隐式的自动装配bean【重要】

8.1测试

  • 测试代码

    • 一个人有两个不同的宠物(Person类、Dog类、Cat类)

 //测试类
 @Test
 public void test() {
     
     ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
     
     Person person = context.getBean("person",Person.class);
     person.getDog.shout();
     person.getCat.shout();
     
 }

8.2ByName自动装配

  • byName: 会自动在容器上下文中查找,和自己对象set方法后面的值对应的beanid。

 <bean id="cat" class="com.shelby.pojo.Cat"/>
 <bean id="dog" class="com.shelby.pojo.Dog"/>
 ​
 <bean id="person" class="com.shelby.pojo.Person" autowire="byName">
     <property name="name" value="小傻子学java"/>
 </bean>

8.3ByType自动装配

  • byType: 会自动在容器上下文中查找,和自己对象属性类型相同的bean。

    • byType把bean中的id去掉,一样可以正常拿到对象,只要确保bean中class的类型唯一且能对应上就可以

 <bean id="cat" class="com.shelby.pojo.Cat"/>
 <bean id="dog" class="com.shelby.pojo.Dog"/>
 ​
 <bean id="person" class="com.shelby.pojo.Person" autowire="byType">
     <property name="name" value="小傻子学java"/>
 </bean>

总结:

  • byname的时候,需要保证所有bean的id唯一,并且这个bean需要和自动注入的属性的setXxx方法的Xxx值一致。

  • bytype的时候,需要保证所有bean的class唯一,并且这个bean需要和自动注入的属性的类型一致。

8.4使用注解的自动装配

  • jdk1.5开始支持的注解,Spring从2.5就开始支持注解了

  • The introduction of annotation-based configuration raised the question of whether this approach is “better” than XML. (摘自Spring官网)

使用注解的步骤:

  1. 导入约束

 <?xml version="1.0" encoding="UTF-8"?>
 <beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:context="http://www.springframework.org/schema/context"
     xsi:schemaLocation="http://www.springframework.org/schema/beans
         https://www.springframework.org/schema/beans/spring-beans.xsd
         http://www.springframework.org/schema/context
         https://www.springframework.org/schema/context/spring-context.xsd">
  1. 配置注解的支持

 <context:annotation-config/>

  • @Autowired

    • 直接在属性上使用。

    • 也可以在set方法上使用。

    • 使用Autowired我们可以不用编写set方法了,前提是自动装配的这个属性在IOC(Spring)容器照顾你存在,且符合名字byName。

科普:

 @Nullable   //字段标记了这个注解,说明这个字段可以为null
 //构造器
 public Person(@Nullable String name) {
     this.name = name;
 }
 public @interface Autowired {
     boolean required() default true;
 }
 //实体类中的一个复杂属性
 //如果我们显示定义了Autowired的required属性值为false,说明这个对象可以为null,否则不允许为空!
 @Atuowired(required = false)
 private Cat cat;
  • @Qualifier

 <bean id="dog1" class="com.shelby.pojo.Dog"/>
 <bean id="dog2" class="com.shelby.pojo.Dog"/>
 @Autowired
 @Qualifier(value="dog1")//如果applicationContext文件中有多个类型相同的bean,可以使用Qualifier来指定使用哪一个bean
 private Dog dog;

注:@Qualifier一般和@Autowired搭配起来使用

如果@Autowired自动装配的环境比较复杂,自动装配无法通过一个注解【@Autowired】完成时,我们可以使用@Qualifier(value="xxx")去配合@Autowired使用,指定一个唯一的bean对象注入!

@ 附件:Spring所需要的依赖及xml文件

  1. 使用Spring所需要导入的依赖

     <!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
     <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-web</artifactId>
         <version>5.2.0.RELEASE</version>
     </dependency>
     ​
     <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
     <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-jdbc</artifactId>
         <version>5.2.0.RELEASE</version>
     </dependency>
  2. ApplicationContext.xml模板【Spring官网有】

 <?xml version="1.0" encoding="UTF-8"?>
 <beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://www.springframework.org/schema/beans
         https://www.springframework.org/schema/beans/spring-beans.xsd">
 ​
     <bean id="..." class="...">  
         <!-- collaborators and configuration for this bean go here -->
     </bean>
 ​
 </beans>

3.p命名空间约束

 xmlns:p="http://www.springframework.org/schema/p"

4.c命名空间约束

 xmlns:p="http://www.springframework.org/schema/c"

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值