Spring总结(一)

一.Spring发展史

  1. 2002年Rod Johnson这个人发布了一篇文章,叫<Expert One-on-One J2EE Design And Development>,因为有了这篇文章,很多人才有了一些感悟,才产生了后面的Spring
  2. 2003年有了Spring,当时只有IOC,AOP两大特性
  3. 经过了这么多年,后面有了Spring Data,Spring Boot,Spring Cloud,Spring Framework,Spring Social等

二.IOC:控制反转(DI:依赖注入)

1.搭建Spring环境

  1. 下载jar包:http://maven.springframework.org/release/org/springframework/spring/(下载4版本就可以), Spring-framework-4.3.9.RELEASE-dist.zip
  2. 下载好的jar包一个jar一般有三个文件(.jar是.class文件 -javadoc.jar是说明文档    -sources.jar是.java文件(源代码))
  3. 开发spring至少需要使用的jar(5个 + 1个)
    • spring-aop.jar      开发AOP特性时需要的jar
    • spring-beans.jar       处理Bean的jar                        <bean>
    • spring-context.jar     处理Spring上下文的jar            <context>
    • spring-core.jar         Spring核心的jar
    • spring-expression.jar         Spring表达式(与EL/JSTL类似)
    • 三方提供的日志jar(百度查:commons-logging.jar mvn,1.1.1版本就可以):commons-logging.jar 

2.编写配置文件(为了编写时有一些提示,自动生成一些配置信息,需要一些插件的支持,当然,也可以手动的copy上去)

  1. 方式一:增加sts插件: 可以给eclipse增加支持spring的插件:spring tool suite (https://spring.io/tools3/sts/all/) 下载与eclipse版本相关的版本。Eclipse中点击 -> Help -> Install New Software -> Add - > 根据下载好的.zip文件或者解压出来的文件夹或者更新网站进行下载插件
  2. 方式二:直接下载sts工具(相当于一个eclipse,就是说eclipse里集成了sts插件):https://spring.io/tools3/sts/all/

3.开发Spring程序(IOC) 

  1. 导入以上的6个jar包:ring-aop.jar,spring-beans.jar,spring-context.jar,spring-core.jar,spring-expression.jar,commons-logging.jar
  2. 创建applicationContext.xml配置文件:右键创建Spring Bean Configuration File文件
    <?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">
        
    <!-- 该文件中产生的所有对象,被Spring放入了一个称之为Spring IOC容器的地方 -->
                    <!-- id:唯一标示符,class:指定类型 -->
                    <bean id="student" class="cn.chuanqi.entity.Student">
                    <!-- 
                        property:该class所代表的类的属性
                        name:属性名
                        value:属性值
                    -->
                    <property name="stuNo" value="1"></property>
                    <property name="stuName" value="张三"></property>
                    <property name="stuAge" value="18"></property>
                </bean>
    </beans>

     

  3. 创建Student实体类
    package cn.chuanqi.entity;
    
    public class Student {
                private Integer stuNo;
                private String stuName;
                private Integer stuAge;
                public Integer getStuNo() {
                    return stuNo;
                }
                public void setStuNo(Integer stuNo) {
                    this.stuNo = stuNo;
                }
                public String getStuName() {
                    return stuName;
                }
                public void setStuName(String stuName) {
                    this.stuName = stuName;
                }
                public Integer getStuAge() {
                    return stuAge;
                }
                public void setStuAge(Integer stuAge) {
                    this.stuAge = stuAge;
                }
                @Override
                public String toString() {
                    return this.stuNo + "-" + this.stuName + "-" + this.stuAge;
                }
    }

     

  4. 创建Test类
    package cn.chuanqi.test;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import cn.chuanqi.entity.Student;
    
    public class Test {
                public static void main(String[] args) {
                    //创建Spring上下文对象
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
                    //执行从Spring IOC容器中获取一个id为student的对象
                    Student student = (Student) context.getBean("student");
                    System.out.println(student);
                }
    }

     

  5. 可以发现,Spring的IOC容器帮我们new了对象,并且给对象赋了值

4.Spring发展史

  1. 原始的创建对象方法:Student student = new Student();              student.setXx(); -> 简单工厂 ->  IOC(超级工厂)
  2. IOC(控制反转)也可以称之为DI(依赖注入),在有一次Spring大会上,大家觉得原始的创建对象,设置属性值到IOC容器中拿的这种反转概念模糊,所以改为DI,当然到现在为止叫IOC和DI都没有错
  3. IOC(控制反转): 将创建对象、属性值的方式进行了反转、从new、setXx()反转为了从Spring IOC容器getBean()
  4. DI(依赖注入): 将属性值注入给了属性,将属性注入给了bean,将bean注入给了IOC容器
  5. 总结:IOC/DI,无论要什么对象,都可以直接去Spring IOC容器中获取,而不需要自己操作(new / setXx()),因此之后的IOC分为2步: 第1步:先给Spring IOC中存放对象并且赋值,第二步:拿

5.DI(依赖注入)

  1. 创建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 http://www.springframework.org/schema/beans/spring-beans.xsd">
        
                <bean id="teacher" class="cn.chuanqi.entity.Teacher">
                    <property name="name" value="张三"></property>
                    <property name="age" value="26"></property>
                </bean>
        
                <bean id="course" class="cn.chuanqi.entity.Course">
                    <property name="courseName" value="Java"></property>
                    <property name="courseHour" value="8"></property>
                    <property name="teacher" ref="teacher"></property>
                </bean>
        
    </beans>

     

  2. 创建Teacher实体类
    package cn.chuanqi.entity;
    
    public class Teacher {
                private String name;
                private String age;
                public String getName() {
                    return name;
                }
                public void setName(String name) {
                    this.name = name;
                }
                public String getAge() {
                    return age;
                }
                public void setAge(String age) {
                    this.age = age;
                }
    }

     

  3. 创建Course实体类
    package cn.chuanqi.entity;
    
    public class Course {
                private String courseName; //课程名称
                private int courseHour; //课时
                private Teacher teacher; //授课老师,依赖于Teacher注入
                public String getCourseName() {
                    return courseName;
                }
                public void setCourseName(String courseName) {
                    this.courseName = courseName;
                }
                public int getCourseHour() {
                    return courseHour;
                }
                public void setCourseHour(int courseHour) {
                    this.courseHour = courseHour;
                }
                public Teacher getTeacher() {
                    return teacher;
                }
                public void setTeacher(Teacher teacher) {
                    this.teacher = teacher;
                }
                @Override
                public String toString() {
    return this.getCourseName() + "-" + this.getTeacher().getName() + "-" + this.getTeacher().getAge() + "-" + this.getCourseHour();
                }
    }

     

  4. 创建Test类
    package cn.chuanqi.test;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import cn.chuanqi.entity.Course;
    
    public class Test {
                public static void main(String[] args) {
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
                    Course course = (Course) context.getBean("course");
                    System.out.println(course);
                }
    }

     

  5. IOC容器赋值:如果是简单类型(8个基本数据类型+String),也叫字面值,用value;如果是对象类型,用ref

6.依赖注入3种方式

  1. set注入:通过setXx()方法赋值
    • 认使用的是set方法()
    • 依赖注入底层是通过反射实现的
    • .xml配置文件中使用<property></property>标签 
  2. 构造器注入:通过构造方法赋值  
    • .xml配置文件中使用<constructor-arg></constructor-arg>标签
    • 需要注意:如果<constructor-arg></constructor-arg>的顺序与构造方法参数的顺序不一致,则需要通过type(参数类型)或者index(参数索引,从0开始)或者name(参数名称)指定顺序,推荐写名字,见名知意
  3. p命名空间注入注意:在构造器注入的时候,无论是String/int/short/long,在赋值时都是value = “值”,字符串形式赋值的。因此建议此种情况需要配合name/type进行区分
    • 引入p命名空间:xmlns:p=http://springframework.org/schema/p
    • 简单类型: p:属性名=“属性值”

    • 引用类型:p:属性名-ref = “引用的id”

    • 注意多个p赋值的时候,中间要留有空格

  4. 示例
    • 注入各种集合数据类型:数组(array),List,Set,Map,Properties
    • 演示
      • 创建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 http://www.springframework.org/schema/beans/spring-beans.xsd">
            
        <bean id="allCollectionType" class="cn.chuanqi.entity.AllCollectionType">
                        <!-- list -->
                        <property name="listElement">
                            <list>
                                <value>足球1</value>
                                <value>篮球1</value>
                                <value>羽毛球1</value>
                            </list>
                        </property>
                
                        <!-- array -->
                        <property name="arrayElement">
                            <array>
                                <value>足球2</value>
                                <value>篮球2</value>
                                <value>羽毛球2</value>
                            </array>
                        </property>
                
                        <!-- set -->
                        <property name="setElement">
                            <set>
                                <value>足球3</value>
                                <value>篮球3</value>
                                <value>羽毛球3</value>
                            </set>
                        </property>
                
                        <!-- map -->
                        <property name="mapElement">
                            <map>
                                <entry>
                                    <key>
                                        <value>football</value>
                                    </key>
                                    <value>足球4</value>
                                </entry>
                                <entry>
                                    <key>
                                        <value>basketball</value>
                                    </key>
                                    <value>篮球4</value>
                                </entry>
                                <entry>
                                    <key>
                                        <value>badminton</value>
                                    </key>
                                    <value>羽毛球4</value>
                                </entry>
                            </map>
                        </property>
                
                        <!-- Properties -->
                        <property name="propsElement">
                            <props>
                                <prop key="football">足球5</prop>
                                <prop key="basketball">篮球5</prop>
                                <prop key="badminton">羽毛球5</prop>
                            </props>
                        </property>
                    </bean>
            
        </beans>
      • 创建AllCollectionType实体类
        package cn.chuanqi.entity;
        
        import java.util.List;
        import java.util.Map;
        import java.util.Properties;
        import java.util.Set;
        
        public class AllCollectionType {
            private List<String> listElement;
            private String[] arrayElement;
            private Set<String> setElement;
            private Map<String, String> mapElement;
            private Properties propsElement;
                        public List<String> getListElement() {
                            return listElement;
                        }
                        public void setListElement(List<String> listElement) {
                            this.listElement = listElement;
                        }
                        public String[] getArrayElement() {
                            return arrayElement;
                        }
                        public void setArrayElement(String[] arrayElement) {
                            this.arrayElement = arrayElement;
                        }
                        public Set<String> getSetElement() {
                            return setElement;
                        }
                        public void setSetElement(Set<String> setElement) {
                            this.setElement = setElement;
            }
                        public Map<String, String> getMapElement() {
                            return mapElement;
                        }
                        public void setMapElement(Map<String, String> mapElement) {
                            this.mapElement = mapElement;
                        }
                        public Properties getPropsElement() {
                            return propsElement;
                        }
                        public void setPropsElement(Properties propsElement) {
                            this.propsElement = propsElement;
                        }
                        @Override
                        public String toString() {
                            String strContent = "";
                            for (String str : arrayElement) {
                            strContent += str + ",";
                        }
        return "listElement:" + this.listElement + "\narrayElement:" + strContent + "\nsetElement:" + this.setElement + "\nmapElement:" + this.mapElement + "\npropsElement:" + this.propsElement;
                    }
        }
      • 创建Test类
        package cn.chuanqi.test;
        
        import org.springframework.context.ApplicationContext;
        
        public class Test {
                        public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        AllCollectionType allCollectionType = (AllCollectionType) context.getBean("allCollectionType");
                            System.out.println(allCollectionType);
                        }
        }
      • 数组(array),Set,List都各自有自己的标签<set>,<list>,<array>,但是也可以混着用

  5. 一些细节
    • value与<value>注入方式的区别
    • 给对象类型赋值null,注意没有<value>

    • 给对象类型赋值“”有两种方式

    • 在IOC中定义Bean的前提:该Bean的类必须提供了无参构造

7.第四种注入方式->自动装配(只试用于ref类型):约定优于配置

  1. autowire = “byName” : Course类中有一个ref属性teahcer(属性名),并且该IOC容器中恰好有一个bean的id也是teacher。ByName本质是byId
  2. byType:根据类型 ,其他bean的类型(class)是否与该Course类的ref属性类型一致。(此种方式,必须满足:当前OC容器中只能有一个Bean满足条件,如果没有找到不会报错,如果有两个相同的ref属性类型,后台报错)
  3. constructor:其他bean的类型(class)是否与该Course类的构造方法参数的类型一致。此种方式的本质就是byType
  4. no:不启用自动注入,只是用ref进行装配注入
  5. default:实际上是会优先执行constructor然后是byType
  6. 全局自动装配:可以在头文件中,一次性将该IOC容器的所有bean,统一设置成自动装配。另外子标签可以覆盖全局性

     

  7. 自动装配虽然可以减少代码量,但是会降低可读性,时候时需要谨慎

8.使用注解定义Bean:通过注解的形式将bean以及相应的属性值放入IOC容器

  1. 引入命名空间

     

  2. 配置扫描器,扫描base-package包下的类,查找这些类是否有注解,比如@Component(“studentDao”),如果有,则将该类加入Spring IOC容器中

     

  3. 如果要扫描多个包,用逗号分割
  4. @Component范围非常大,Servlet,Service,Dao都可以用。(可以用于注册所有bean)

  5.  

    Dao层注解:@Repository (主要用于注册dao层的bean)
  6. Service层注解:@Service (主要用于注册服务层的bean)
  7. Servlet层注解:@Controller (主要用于注册控制层的bean)
  8. @Resource:java的注解,默认以byName的方式去匹配与属性名相同的bean的id,如果没有找到就会以byType的方式查找,如果byType查找到多个的话,使用@Qualifier注解(spring注解)指定某个具体名称的bean
  9. @Autowired:spring注解,默认是以byType的方式去匹配与属性名相同的bean的id,如果没有找到,就通过byName的方式去查找

posted @ 2019-07-25 10:22  Java-Legend  阅读(202)  评论(0编辑  收藏  举报