紫玉坏小子

导航

Spring学习

Spring学习

Spring概述

Spring是另一个主流的java Web开发框架,该框架是一个轻量级的开源的应用框架,具有很高的凝聚力和吸引力、可以解决企业应用开发的复杂性。Spring框架因其强大的功能以及卓越的性能而受到众多开发人员的喜爱。

Spring 是分层的 Java SE/EE full-stack 轻量级开源框架,以 IoC(Inverse of Control,控制反转):把创建对象过程交给Spring进行管理和 AOP(Aspect Oriented Programming,面向切面编程)为内核,使用基本的 JavaBean 完成以前只可能由 EJB 完成的工作,取代了 EJB 臃肿和低效的开发模式。

在实际开发中,通常服务器端采用三层体系架构,分别为表现层(web)、业务逻辑层(service)、持久层(dao)。

Spring 具有简单、可测试和松耦合等特点,不仅可以用于服务器端的开发,也可以应用于任何 Java 应用的开发中。Spring 框架的主要优点具体如下。

1)方便解耦,简化开发

Spring 就是一个大工厂,可以将所有对象的创建和依赖关系的维护交给 Spring 管理。

2)方便集成各种优秀框架

Spring 不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如 Struts2、Hibernate、MyBatis 等)的直接支持。

3)降低 Java EE API 的使用难度

Spring 对 Java EE 开发中非常难用的一些 API(JDBC、JavaMail、远程调用等)都提供了封装,使这些 API 应用的难度大大降低。

4)方便程序的测试

Spring 支持 JUnit4,可以通过注解方便地测试 Spring 程序。

5)AOP 编程的支持

Spring 提供面向切面编程,可以方便地实现对程序进行权限拦截和运行监控等功能。

6)声明式事务的支持

只需要通过配置就可以完成对事务的管理,而无须手动编程。

  • Spring 框架采用分层架构,根据不同的功能被划分成了多个模块,这些模块大体可分为 Data Access/Integration、Web、AOP、Aspects、Messaging、Instrumentation、Core Container 和 Test,如图 1 所示。

图 1 中包含了 Spring 框架的所有模块,这些模块可以满足一切企业级应用开发的需求,在开发过程中可以根据需求有选择性地使用所需要的模块。下面分别对这些模块的作用进行简单介绍。

1. Data Access/Integration(数据访问/集成)

数据访问/集成层包括 JDBC、ORM、OXM、JMS 和 Transactions 模块,具体介绍如下。

  • JDBC 模块:提供了一个 JDBC 的抽象层,大幅度减少了在开发过程中对数据库操作的编码。

  • ORM 模块:对流行的对象关系映射 API,包括 JPA、JDO、Hibernate 和 iBatis 提供了的集成层。

  • OXM 模块:提供了一个支持对象/XML 映射的抽象层实现,如 JAXB、Castor、XMLBeans、JiBX 和 XStream。

  • JMS 模块:指 Java 消息服务,包含的功能为生产和消费的信息。

  • Transactions 事务模块:支持编程和声明式事务管理实现特殊接口类,并为所有的 POJO。

2. Web 模块

Spring 的 Web 层包括 Web、Servlet、Struts 和 Portlet 组件,具体介绍如下。

  • Web 模块:提供了基本的 Web 开发集成特性,例如多文件上传功能、使用的 Servlet 监听器的 IoC 容器初始化以及 Web 应用上下文。

  • Servlet模块:包括 Spring 模型—视图—控制器(MVC)实现 Web 应用程序。

  • Struts 模块:包含支持类内的 Spring 应用程序,集成了经典的 Struts Web 层。

  • Portlet 模块:提供了在 Portlet 环境中使用 MV C实现,类似 Web-Servlet 模块的功能。

3. Core Container(核心容器)

Spring 的核心容器是其他模块建立的基础,由 Beans 模块、Core 核心模块、Context 上下文模块和 Expression Language 表达式语言模块组成,具体介绍如下。

  • Beans 模块:提供了 BeanFactory,是工厂模式的经典实现,Spring 将管理对象称为 Bean。

  • Core 核心模块:提供了 Spring 框架的基本组成部分,包括 IoC 和 DI 功能。

  • Context 上下文模块:建立在核心和 Beans 模块的基础之上,它是访问定义和配置任何对象的媒介。ApplicationContext 接口是上下文模块的焦点。

  • Expression Language 模块:是运行时查询和操作对象图的强大的表达式语言。

4. 其他模块

Spring的其他模块还有 AOP、Aspects、Instrumentation 以及 Test 模块,具体介绍如下。

  • AOP 模块:提供了面向切面编程实现,允许定义方法拦截器和切入点,将代码按照功能进行分离,以降低耦合性。

  • Aspects 模块:提供与 AspectJ 的集成,是一个功能强大且成熟的面向切面编程(AOP)框架。

  • Instrumentation 模块:提供了类工具的支持和类加载器的实现,可以在特定的应用服务器中使用。

  • Test 模块:支持 Spring 组件,使用 JUnit 或 TestNG 框架的测试。

Spring入门案例

  • 下载Spring框架

进入页面后 向下拉 找到下图位置

点进去 找到下图位置

出现的 https://repo.spring.io就是下载地址

  • Spring入门需要这5个jar

    加载jar步骤

  • 创建一个User实体类

    public class User {
       public void add(){
           System.out.println("add....");
      }
    }
  • 配置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 http://www.springframework.org/schema/beans/spring-beans.xsd">

       <bean id="user" class="com.company.User"></bean>
    </beans>
  • 创建一个测试类

    public class SpringTest {
       @Test
       //springdemo.xml在src下
       public void testAdd(){
           ApplicationContext context = new ClassPathXmlApplicationContext("springdemo.xml");
           User user = (User) context.getBean("user");
           user.add();
      }
    }

     

    IOC(控制反转)

    • 什么是控制反转?

      • 是面向对象编程的一种设计原则,可以用来减低计算机代码之间的耦合性,其中最常见的方式叫做依赖注入(DI)

      • 把对象创建和对象之间的调用过程,交给Spring进行管理

    • IOC底层原理

      • xml解析,工厂那个模式、反射

      • IOC重要的接口

        • IOC思想基于IOC容器完成,IOC容器底层就是对象工厂

        • spring提供IOC容器实现两种方式(两个接口)

          • BeanFactory :IOC容器基本实现(Spring自带接口,一般开发不使用),* 加载配置文件时候不会创建对象,在获取对象(使用对象)才会创建对象

          • ApplicationContext:BeanFactory 的子接口,提供更多,更强大的功能(一般由开发人员进行使用),*加载配置文件时候会把配置文件对象进行配置

        • ApplicationContext接口的实现类

          • FileSystemXmlApplicationContext:盘符路径(全路径)

          • ClassPathXmlApplicationContext:目录路径

    • IOC:Bean管理xml

      • 什么是Bean管理(2个操作)

        • Spring创建对象

        • Spring注入属性

      • Bean管理的两种方式

        • 基于xml配置文件实现

          • 基于xml方式创建对象

            • 在Spring配置文件中,使用bean标签,标签里添加相应的属性,就可以实现创建对象

            • 在bean标签有很多属性

              • id属性:表示给对象起一个唯一标识

              • class属性:创建对象所在类的全路径

              • name属性:和id属性类似,用的不多,区别在于id属性中不能加入特殊属性,name属性可以

              • 创建对象时候,默认执行无参构造方法完成对象创建

            • <bean id="user" class="com.company.User"></bean>
          • 基于xml方式注入属性

            • DI:依赖注入,就是注入属性

               @Test
                 //springdemo.xml在src下
                 public void testAdd(){
                     ApplicationContext context = new ClassPathXmlApplicationContext("springdemo.xml");
                     User user = (User) context.getBean("user");
                     user.add();
                     System.out.println(user.getbName());
                }
               <!-- 创建User对象-->
                 <bean id="user" class="com.company.User">
                     <!-- set方法注入属性 注意 实体类中要对属性进行set***()否则报错-->
                     <property name="bName" value="张三"></property>
                 </bean>

              name属性:对象的属性字段

              value属性:注入对象属性

              有参构造方法注入属性

              public class Book {
                 private String bName;
                 private String author;

                 public Book(String bName, String author) {
                     this.bName = bName;
                     this.author = author;
                }

                 public Book() {
                }
              }
              @Test
                 //springdemo.xml在src下
                 public void testAdd(){
                     ApplicationContext context = new ClassPathXmlApplicationContext("springdemo.xml");
                     Book book = (Book) context.getBean("book");
                     System.out.println(book.toString());
                }
              <bean id="book" class="com.company.Book">
                     <!-- 有参构造方法注入属性-->
                     <constructor-arg  name="author" value="张三"></constructor-arg>
                     <constructor-arg  name="bName" value="有参构造注入"></constructor-arg>
                 <!--       <constructor-arg index="0" value="oo"></constructor-arg>-->
                 </bean>

              index属性:实体类中属性的下标

        • IOC操作Bean管理(xml注入其他类型属性)

          • 字面量

            • null值

              <!-- 创建User对象-->
                 <bean id="user" class="com.company.User">
                     <!-- set方法注入属性-->
                     <property name="bName" value="张三"></property>
                     <!--null-->
                     <property name="age">
                         <null/>
                     </property>
                 </bean>

               

            • 属性值包含特殊符号

               <!-- 创建User对象-->
                 <bean id="user" class="com.company.User">
                     <!-- 属性值中含有特殊符号-->
                     <property name="bName" >
                         <value>
                             <![CDATA[《南京》]]>
                         </value>
                     </property>
                 </bean>
            • 注入外部Bean

              public class User {

                 private int age;
                 private String bName;
                 private  Book book;
                 public void add(){
                     System.out.println("add....");
                }

                 public void setbName(String bName) {
                     this.bName = bName;
                }

                 public String getbName() {
                     return bName;
                }

                 public Book getBook() {
                     return book;
                }

                 public void setBook(Book book) {
                     this.book = book;
                }

                 public int getAge() {
                     return age;
                }

                 public void setAge(int age) {
                     this.age = age;
                }
              }
              <!-- 创建User对象-->
                 <bean id="user" class="com.company.User">
                     <!-- 属性值中含有特殊符号-->
                     <property name="bName" >
                         <value>
                             <![CDATA[《南京》]]>
                         </value>
                     </property>
                     <property name="book" ref="book"></property>
                 </bean>
                @Test
                 //springdemo.xml在src下
                 public void testAdd(){
                     ApplicationContext context = new ClassPathXmlApplicationContext("springdemo.xml");
                     Book book = (Book) context.getBean("book");
              //       System.out.println(book.toString());
                     User user = (User) context.getBean("user");
                     System.out.println(user.getBook().toString());
                }

        ref属性:引用外部对象

        • 注入属性---内部bean

          • 一对多关系:部门dept和员工Emp

            一个部门有多个员工,一个员工属于一个部门

          • 在实体类之间表示一对多关系

            部门类

            public class Dept {
               private String name;
               public void setName(String name) {
                   this.name = name;
              }
               @Override
               public String toString() {
                   return "Dept{" +
                           "name='" + name + '\'' +
                           '}';
              }
            }

            员工类

            public class Emp {
               private String name;

               private int age;

               private Dept dept;

               public void setDept(Dept dept) {
                   this.dept = dept;
              }

               public void setName(String name) {
                   this.name = name;
              }

               public void setAge(int age) {
                   this.age = age;
              }

               @Override
               public String toString() {
                   return "Emp{" +
                           "name='" + name + '\'' +
                           ", age=" + age +
                           ", dept=" + dept.toString() +
                           '}';
              }
            }

            配置文件

            <bean name="emp" class="com.company.Bean.Emp">
                   <property name="name" value="张三"/>
                   <property name="age" value="45"/>
                   <property name="dept">
                       <bean name="dept" class="com.company.Bean.Dept">
                           <property name="name" value="开发部" />
                       </bean>
                   </property>
               </bean>

            测试

            Emp{name='张三', age=45, dept=Dept{name='开发部'}}
        • 注入属性---级联赋值(注意要生成getDept()方法)

          <bean  name="dept" class="com.company.Bean.Dept"></bean>
             <bean name="emp" class="com.company.Bean.Emp">
                 <property name="dname" value="张三"/>
                 <property name="age" value="45"/>
                 <property name="dept"  ref="dept" />
                 <property name="dept.name"  value="开发部" />
             </bean>
        数组类型注入属性
        • 创建实体类 并创建set方法

          public class Student {

             private String[] strings;

             private List<String> list;

             private Map<String,String> map;

             private Set<String> set;

             private List<User> userList;

             public void setUserList(List<User> userList) {
                 this.userList = userList;
            }
             
             public void setStrings(String[] strings) {
                 this.strings = strings;
            }

             public void setList(List<String> list) {
                 this.list = list;
            }

             public void setMap(Map<String, String> map) {
                 this.map = map;
            }

             public void setSet(Set<String> set) {
                this.set = set;
            }
          }
        • 配置文件

          <bean name="stu" class="com.company.collect.Student">
                <property name="strings" >
                    <array>
                        <value>String1</value>
                        <value>String2</value>
                    </array>
                </property>
                <property name="list">
                    <list>
                        <value>list1</value>
                        <value>list2</value>
                    </list>
                </property>
                <property name="map">
                    <map>
                        <entry key="JAVA" value="java"></entry>
                    </map>
                </property>
                <property name="set">
                    <set>
                        <value>set1</value>
                        <value>set2</value>
                    </set>
                </property>

            </bean>
        • 结果

          Student{strings=[String1, String2], list=[list1, list2], map={JAVA=java}, set=[set1, set2]}
        • 在集合里面设置对象类型值
           <property name="userList">
                    <list>
                        <ref bean="user" ></ref>  
                    </list>
                </property>
           <!-- 创建User对象-->
             <bean id="user" class="com.company.User">
                 <!-- 属性值中含有特殊符号-->
                 <property name="bName" >
                     <value>
                         <![CDATA[《南京》]]>
                     </value>
                 </property>
             </bean>
        • 百度查询 把集合值提取出来当成一个公共值

        • 工厂Bean (返回的类型可以和定义的类型不一致)

          工厂bean

          package com.company.factory;

          import com.company.Bean.Emp;
          import org.springframework.beans.factory.FactoryBean;
          import org.springframework.context.ApplicationContext;
          import org.springframework.context.support.ClassPathXmlApplicationContext;

          public class Factory implements FactoryBean<Person> {
             @Override
             public Person getObject() throws Exception {
                 Person person = new Person();
                 person.name= "张三";
                 return person;
            }

             @Override
             public Class<?> getObjectType() {
                 return null;
            }

             @Override
             public boolean isSingleton() {
                 return false;
            }



             public static void main(String[] args) {
                 ApplicationContext context = new ClassPathXmlApplicationContext("factory.xml");
                 Person fct = context.getBean("fct", Person.class);
                 System.out.println(fct.toString());
            }
          }

          返回bean

          package com.company.factory;

          public class Person {
             public  String name;

             @Override
             public String toString() {
                 return "Person{" +
                         "name='" + name + '\'' +
                         '}';
            }
          }
        • bean的单实例还是多实例的属性
          scope="prototype"  多实例      scope属性
          scope="singleton" 单实例
        • bean的初始方法和销毁方法 (百度查询 bean的生命周期)

          init-method:初始方法
          destroy-method:销毁方法
          (ClassPathXmlApplicationContext)context.close(); 手动销毁bean
        •  

      •  

        • 基于注解方式实现

  •  

    • 什么是注解

      • 注解是代码特殊标记,格式:@注解名称(属性名称=属性值,属性名称=属性值)

      • 使用注解,注解作用在类上面,方法上面,属性上面

      • 使用注解的目的:简化xml配置

    • Spring针对Bean管理中创建对象提供注解 基于注解创建对象

      • @Component

      • @Service

      • @Controller

      • Repository

      • 上面四个注解功能是一样的,都可以用来创建Bean实例

    • 基于注解实现的步骤

        1. 加入依赖

          • spring-aop-***.jar

        2. 创建扫描器

          • <?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 http://www.springframework.org/schema/beans/spring-beans.xsd
                  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

               <context:component-scan base-package="com.pack.it" ></context:component-scan>
            </beans>
    1. 创建实体类 并加上注解

      package com.pack.it;

      import org.springframework.stereotype.Repository;

      @Repository
      public class User {
         private  String name;
         @Override
         public String toString() {
             return "User{" +
                     "name='" + name + '\'' +
                     '}';
        }
         public String getName() {
             return name;
        }
         public void setName(String name) {
             this.name = name;
        }
      }
      1. 测试类(上面四个注解都是一样的)

          @Test
           public  void  test(){
               ApplicationContext context =
                       new ClassPathXmlApplicationContext("UserXml.xml");
               User user = context.getBean("user", User.class);
               user.setName("张三");
               System.out.println(user.toString());
          }

     

    • 基于注解 的扫描 细节

       <!-- 
         use-default-filters="false :表示不全扫描所有的类  
         context:include-filter :只扫描包里带有Controller的注解
         context:exclude-filter:扫描除了包里带有Service的注解
         -->
         <context:component-scan base-package="com.pack" use-default-filters="false">
             <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
             <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
         </context:component-scan>
    • 基于注解实现属性注入

      • @Autowired
        @Resource
        @Qualifier
        @Value
    • @Autowired:根据你的属性类型进行自动装配

      • 第一步:把service和dao对象创建,在service和dao类上添加创建对象注解

      • 第二步:把service注入dao对象,在service类添加dao类型属性,在属性上使用注解

      • @Repository
        public class UserDaoImpl implements UserDao {
           @Override
           public void say() {
               System.out.println("daoImpl......");
          }
        }
      • public interface UserDao {
           public  void  say();
        }

      • @Service
        public class UserService {
           @Autowired
           private UserDao userDao;

           public void say(){
               System.out.println("userService....");
               userDao.say();
          }
        }
      •  

    • Qualifier:根据属性名称注入

      • 判断使用具体的哪一个类注入 (根据定义的名称)

      • @Repository(value = "userDaoImpl")
        public class UserDaoImpl implements UserDao {
           @Override
           public void say() {
               System.out.println("daoImpl......");
          }
        }
      •  

      •     @Autowired
           @Qualifier(value = "userDaoImpl")
           private UserDao userDao;

           public void say(){
               System.out.println("userService....");
               userDao.say();
          }
      •  

    • @Resource:上面两种的功能集成

      • @Service
        public class UserService {
           // @Resource //根据属性类型注入
           @Resource(name = "userDaoImpl") //根据名称注入
           private UserDao userDao;

           public void say(){
               System.out.println("userService....");
               userDao.say();
          }
        }
      •  

    • @Value:注入普通类型属性 主要是不是对象的普通类型

      • @Service
        public class UserService {

           // @Resource //根据属性类型注入
           @Resource(name = "userDaoImpl") //根据名称注入
           private UserDao userDao;
           @Value(value = "26366")
           private String name;

           public void say(){
               System.out.println("userService...."+name);
               userDao.say();
          }
        }
    • 完全注解开发

      • @Configurable  //作为配置类 代替xml文件
        @ComponentScan(basePackages = {"com.pack"})
        public class SpringConfig {
        }
      •    @Test
           public  void  test(){
               ApplicationContext context =
                       new AnnotationConfigApplicationContext(SpringConfig.class);
               UserService user = context.getBean("userService", UserService.class);
               user.say();
          }
      •  

posted on 2021-01-12 21:11  紫玉坏小子  阅读(27)  评论(0编辑  收藏  举报