Spring框架入门简述

Spring框架1 - 入门简述

框架

首先我们要理解框架是什么?框架跟类库有什么区别?

框架,框架其实是一个半成品,它对基础的代码进行了封装并提供相应的API,开发者在使用框架是直接调用封装好的api可以省去很多代码编写,从而提高工作效率和开发速度。
其组成部分: jar包、配置文件(全局+单元)、启动代码等。

类库,类库(Class Library),字面意思就是类的集合,是一个综合性的面向对象的可重用类型集合,这些类型包括:接口、抽象类和具体类。

如何学习框架?
对于框架的学习,我们应该要理解框架的理念以及要解决的问题、学习它的配置和调用方式(其实可以理解为如何套用)、按照套路编码。

什么是Spring?

  • Spring 是最受欢迎的企业级 Java 应用程序开发框架,是为了解决企业应用程序开发复杂性而创建的。

  • Spring 框架是一个开源的 Java 平台,它最初是由 Rod Johnson 编写的,并且于 2003 年 6 月首次在 Apache 2.0 许可下发布。

  • Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。Spring使用基本的JavaBean来完成以前只可能由EJB(Enterprise Java Bean)完成的事情。

  • Spring 框架的核心特性是可以用于开发任何 Java 应用程序,但是在 Java EE 平台上构建 web 应用程序是需要扩展的。 Spring 框架的目标是使 J2EE 开发变得更容易使用,通过启用基于 POJO 编程模型来促进良好的编程实践。

Spring框架的好处

1.放便解耦,简单开发
通过Spring提供的IoC容器,我们可以将对象之间的依赖关系交由Spring进行控制,避免硬编码所造成的过度程序耦合。有了Spring,用户不必再为单实例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。

2.Aop 编程支持
通过Spring提供的AOP功能,方便进行面向切面的编程,许多不容易用传统OOP实现的功能可以通过AOP轻松应付。

3.声明事务的支持
在Spring中,我们可以从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理,提高开发效率和质量。

4.方便程序的测试
可以用非容器依赖的编程方式进行几乎所有的测试工作,在Spring里,测试不再是昂贵的操作,而是随手可做的事情。例如:Spring对Junit4支持,可以通过注解方便的测试Spring程序。

5.方便框架的集合
Spring不排斥各种优秀的开源框架,相反,Spring可以降低各种框架的使用难度,Spring提供 了对各种优秀框架(如Struts、Hibernate、Hessian、 Quartz) 等的直接支持。

6.降低开发难度
Spring对很多难用的Java EE API (如JDBC, JavaMail, 远程调用等)提供了一-个薄薄的封装层, 通过Spring的简易封装,这些Java EE API的使用难度大为降低。

Spring核心概念简述

控制反转(IoC):即Inversion of Control。举例来说,在以前的项目中,要想调用一个类中的普通方法,则必须创建这个类的实例,再通过这个实例来调用其方法。而在Spring中,你不必再使用这种形式来创建对象,具体过程都交由Spring进行配置来实现。

面向切面编程(AOP):aop是一种编程技术,它允许程序员对横切关注点或横切典型的职责分界线的行为(例如日志和事务管理)进行模块化。AOP 的核心构造是切面,它将那些影响多个类的行为封装到可重用的模块中。

Spirng模块


组成 Spring 框架的每个模块(或组件)都可以单独存在,或者与其他一个或多个模块联合实现。每个模块的功能如下:

  • 核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转 (IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。

  • Spring 上下文:Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。

  • Spring AOP:通过配置管理特性,Spring AOP 模块直接将面向方面的编程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何对象支持 AOP。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中。

  • Spring DAO:JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。

  • Spring ORM:Spring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。

  • Spring Web 模块:Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。所以,Spring 框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。

  • Spring MVC 框架:MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。

  • spring-beans : ioc 实现,配置文件的访问、创建和管理

  • SpEL : spring的表达式支持

  • Aspects: 对AspectJ框架的支持

  • instrumentation: 字节码操作

  • messaging : 对消息服务的支持

  • transactions : 事务支持

  • JDBC : spring对JDBC的封装

  • ORM : spring对于ORM框架的支持

  • web : 对于web开发的支持

Spring项目示例

核心理念: IoC inversion of control 控制反转 / DI dependency injection 依赖注入

控制权从调用的类转换到spring容器,由spring来实例化对象及依赖注入

1) 创建对象 2)依赖注入 ( 为属性填入实例)

Spring项目搭建(基于Idea)

建一个简单的登录项目吧。

之前已经配置好了maven,在此就不多说。

导包

在pom.xml加入依赖。自动导入jar包

 <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.0.RELEASE</version>
  </dependency>
搭建结构

DAO

public interface UserDAO {
    String login(String username, String password);
}

DAO实现

public class UserDAOImpl implements UserDAO {
   @Override
   public String login(String username, String password) {
		//暂时不与数据库交互,直接返回字符串测试是否执行
       return "UserDAOImpl执行了。。。";
   }
}

Service

public interface UserService {
    String login(String username, String password);
}

Service实现

public class UserServiceImpl implements UserService {
	//此时我们声明UserDAO,但并不创建对象
    private UserDAO userDAO;
    @Override
    public String login(String username, String password) {
		//直接通过声明调用方法
        return userDAO.login(username,password);
    }
    //创建setter方法
    public void setUserDAO(UserDAO userDAO) {
        this.userDAO = userDAO;
    }
}

Controller

public class UserController {
    //声明userService
    private UserService userService;
    
    public String login(String username,String password){
    	//通过声明直接调用方法
        return userService.login(username,password);
    }
    //创建setter方法
    public void setUserService(UserService userService) {
        this.userService = userService;
    }
}
创建xml文件并配置

在这里插入图片描述

创建applicationContext.xml。通过bean标签来引入具体的类。注意引入的是实现类,满足面向接口编程。

<?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">
    
    <!--通过setter注入-->
    <bean id="userController" class="com.alter.spring.controller.UserController">
        <!--通过ref引入已存在的bean-->
        <property name="userService" ref="userService"/>
    </bean>

    <bean id="userService" class="com.alter.spring.service.impl.UserServiceImpl">
        <property name="userDAO" ref="userDAO"/>
    </bean>

    <bean id="userDAO" class="com.alter.spring.dao.impl.UserDAOImpl"/>

</beans>
编写测试类
public class App {
    public static void main(String[] args) {
        //创建一个spring容器
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        //从容器中获取一个叫做userController的bean并转换为userController的实例
        UserController userController = ac.getBean("userController", UserController.class);
        //调用
        String result = userController.login("abc", "123");
        System.out.println(result);
    }
}

运行之后打印如下:
在这里插入图片描述
从这个例子可以看出,spring框架通过xml配置来获得实例,我们可以将Ioc理解成一个容器,通过xml配置来获得bean实例,并将这些实例保存在容器中。
但是得到实例之后里面的属性又如何注入呢?bean实例化配置只有这种方法吗?
下面我们就讲一讲xml其他的配置方式

xml具体配置方式
1. xml属性配置(下面以UserController为例)
  • 通过value 注入基本类型
    首先我们在controller加入一个基本类型的属性age

    public class UserController {
       //基本属性age
       private String age;
       //setter方法
       public void setAge(String age) {
           this.age = age;
       }
       ...
    }
    

    xml配置:

    <bean id="userDAO" class="com.alter.spring.dao.impl.UserDAOImpl">
       	<!-- 通过value配置基本属性-->
       	<property name="age" value="18" />
       </bean>
    
  • ref 注入已有的bean
    java类:

    public class UserController {
       //声明userservice
       private UserService userService;
       //setter方法
       public void setUserService(UserService userService) {
           this.userService = userService;
       }
       ...
    }
    

    xml配置:

    <bean id="userController" class="com.alter.spring.controller.UserController">
    	<!-- 通过ref配置容器中已存在的bean-->
    	<property name="userService" ref="userService"/>
    </bean>
    
  • List \ Set \ Map等复杂类型配置
    java配置

    public class UserController {
    	//声明list集合
    	private List<String> list;
    	//创建setter方法
        public void setList(List<String> list) {
            this.list = list;
        }
    	//声明map集合
        private Map<String, String> map;
    	//创建setter方法	    
        public void setMap(Map<String, String> map) {
            this.map = map;
        }
    	//声明set集合
        private Set<Integer> set;
    	//创建setter方法	    
        public void setSet(Set<Integer> set) {
            this.set = set;
        }
        ...
    }
    

    xml配置

    <bean id="userDAO" class="com.alter.spring.controller.UserController">   
    	<!-- 通过name指定List属性名,value配置具体的属性值-->
       <property name="list">
           <list>
               <value>manager</value>
               <value>farmer</value>
               <value>driver</value>
           </list>
       </property>
       <!-- 通过name指定Map属性名,<entry>配置具体的属性值-->
       <property name="map">
           <map>
               <entry key="pig" value="pink"/>
               <entry key="cat" value="orange"/>
           </map>
       </property>
       <!-- 通过name指定Set属性名,value配置具体的属性值-->
       <property name="set" >
           <set>
               <value>2</value>
           </set>
       </property>
    </bean>
    

    最后我们验证这些属性是否配置成功,在login方法中加入输出语句。

    public class UserController{
    	...
    	
    	public String login(String username,String password){
            System.out.println("age="+age);
            System.out.println("list="+list);
            System.out.println("map="+map);
            System.out.println("set="+set);
            return userService.login(username,password);
        }
    }
    

    这时IDEA打印如下,说明属性配置成功。
    在这里插入图片描述

2. bean的实例化
  • 默认构造器实例化
    上述的实例中,在xml文件中配置bean实例其实是调用指定类的默认的无参构造方法。(可以给定其有参构造,此时就会抛出异常,在此省略验证步骤)

  • 静态工厂方法实例化

     <!--用静态工厂方法创建一个connection作为springbean-->
    <bean id="connection" factory-method="getConnection" class="com.alter.spring.common.JDBCUtils"/>
    <!--某个类(JDBCUtils)的静态方法(getConnection),返回值作为bean-->
    
  • 工厂bean实例化

      <!--工厂bean-->
       <bean id="holidayFactory" class="com.alter.spring.factory.HolidayFactory"/>
       <!--holidayBean-->
       <bean id="holiday" factory-bean="holidayFactory" factory-method="create"></bean>
       
       public class HolidayFactory {
           public Holiday create(){
               return new Holiday();
           }
       }
    
  • Spring的FactoryBean接口实例化

    • 一个类实现FactoryBean接口,实现其方法

    • 配置之后,bean的实例为FactoryBean的getObject方法的返回值

         public class CarFactory implements FactoryBean<Car> {
         
             @Override
             public Car getObject() throws Exception {
                 return new Car();
             }
         
             @Override
             public Class<?> getObjectType() {
                 return Car.class;
             }
         }
      
        <bean id="car" class="com.alter.spring.factory.CarFactory"/>
      
3. 核心API
  • BeanFactory IOC容器的基本接口
  • ApplicationContext 可用的IOC容器接口
  • ClassPathXmlApplicationContext xml配置文件的IOC容器
4. 依赖注入
  • setter注入
    如上面的例子就是采用setter方法注入属性。
  • 构造器注入
    • <constructor-arg name index>

      • index : 用于指定要注入的数据给构造函数中指定索引位置的参数赋值,索引的位置时从0开始
      • name(常用) : 用于指定给构造函数中指定名称的参数赋值
    • 设置 value ref list set

      <bean id="userService" scope="singleton" class="com.alter.spring.injection.UserServiceImpl" >
          //可以使用name
          <constructor-arg name="userDAO" ref="userDAO"></constructor-arg>
          <constructor-arg name="serviceId" value="12306"/>
          <constructor-arg name="data" >
          //或者使用index    
          <constructor-arg index="0" ref="userDAO"></constructor-arg>
          <constructor-arg index="1" value="12306"/>
          <constructor-arg index="2" >
              <list>
                  <value>xiong</value>
                  <value>nian</value>
                  <value>haha</value>
              </list>
          </constructor-arg>
      </bean>
      
      public class UserServiceImpl implements UserService {
          private UserDAO userDAO;
          private int serviceId;
          private List<String> data;
      
          public UserServiceImpl(UserDAO userDAO,int serviceId,List<String> data){
              this.userDAO = userDAO;
              this.serviceId=serviceId;
              this.data =data;
          };
      }
      

      特点:在获取 bean 对象时,注入数据是必须的操作,否则无法操作成功

      弊端:改变了 bean 对象的实例化方式,使我们在用不到这些数据的情况下也必须提供带参构造函数,因此开发中较少使用此方法,除非避无可避

5. bean的作用域 默认单例
  • prototype 原型 => 每次创建一个实例
  • [*]singleton 单例 => 一个bean的定义,只有一个实例,不是一个类只有一个实例
  • request 一个请求一个实例
  • session 一个会话一个实例
  • websocket 一次websocket链接一个实例
6. bean的生命周期
  • 在bean配置上写init-method和destroy-method

    <bean id="cycle" class="com.alter.spring.lifeCycle.Cycle" init-method="beginning" 
          destroy-method="ending"/>
    
    public class Cycle {
        public void beginning(){
            System.out.println("开始");
        }
        public void ending(){
            System.out.println("结束");
        }
    }
    
  • 实现InitializingBean和DisposableBean及其方法

    <bean id="cycle2" class="com.alter.spring.lifeCycle.Cycle2"/>
    //因为实现了接口,spring可以识别,所以不需要写intit和destroy
    
    public class Cycle2 implements InitializingBean, DisposableBean {
    
        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.println("开始....");
        }
    
        @Override
        public void destroy() throws Exception {
            System.out.println("结束了....");
        }
    }
    
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值