Spring framework 入门

主要是对代码进行解耦和。

简介

spring源码是graddle构建

springframework 是spring 里面的一个基础开源框架,主要用于javaee的企业开发。Spring是什么呢?首先它是一个开源的项目,而且非常活跃;它是一个基于IOC和AOP构架的多层j2ee系统框架,但它不强迫你必须在每一层中必须使用Spring,因为它模块化的很好,允许你根据自己的需要选择使用它的某一个模块;它实现了很优雅的MVC,对不同的数据访问技术提供了统一的接口,采用IOC使得可以很容易的实现bean(普通的java类可以称为一个javaBean)的装配,提供了简洁的AOP(通过 创建代理对象实现对目标对象的功能扩展)并据此实现Transaction Management

full-stack :一站式开源框架。在web项目的各层都提供了解决方案

Spring是一个开源框架,它由Rod Johnson创建。它是为了解决企业应用开发的复杂性而创建的。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。

Spring是一个一站式的轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。

轻量——从大小与开销两方面而言Spring都是轻量的。完整的Spring框架可以在一个大小只有1MB多的JAR文件里发布。并且Spring所需的处理开销也是微不足道的。此外,Spring是非侵入式的:典型地,Spring应用中的对象不依赖于Spring的特定类。(单例)

控制反转——Spring通过一种称作控制反转(IoC)的技术促进了松耦合。当应用了IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。你可以认为IoC与JNDI相反——不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。

面向切面——Spring提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务(transaction)管理)进行内聚性的开发。应用对象只实现它们应该做的——完成业务逻辑——仅此而已。它们并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。

容器——Spring包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器,你可以配置你的每个bean如何被创建——基于一个可配置原型(prototype),你的bean可以创建一个单独的实例或者每次需要时都生成一个新的实例——以及它们是如何相互关联的。然而,Spring不应该被混同于传统的重量级的EJB容器,它们经常是庞大与笨重的,难以使用。

框架——Spring可以将简单的组件配置、组合成为复杂的应用。在Spring中,应用对象被声明式地组合,典型地是在一个XML文件里。Spring也提供了很多基础功能(事务管理、持久化框架集成等等),将应用逻辑的开发留给了你。

所有Spring的这些特征使你能够编写更干净、更可管理、并且更易于测试的代码。它们也为Spring中的各种模块提供了基础支持。

spring版本

  • 3.x

支持java5

  • 4.x

支持java8

  • 5.x

去除java9依赖,支持高版本java

spring相关下载

版本:release snapshot

  • Spring体系架构

spring提供了web各层的解决方案,可以和当前主流的框架进行整合。

掌握

spring的核心框架:beans core context expression

eclipse安装STL(spring tool)插件

1. Spring IOC(invocation of control) 控制反转

将对象的创建权交给spring容器来管理。去new过程。

User user = new User();// 程序和User的耦合度较高
​
class UserService{
​
    UserDao dao = new UserDaoImpl();x
    UserDao dao = new UserDaoMybatisImpl();
    UserDao  dao = DaoFactory.getUserDao();
    
}

底层原理

总结:

IOC就是使用反射+配置文件+工厂模式,去除new关键字,将对象的创建权交给工厂来完成。

1.1 spring 入门环境搭建

    1. 创建java工程

    2. 引入spring的核心依赖:spring-beans.jar spring-core.jar spring-context.jar spring-expression.jar spring-jcl.jar(增加的spring的日志依赖)

    3. 创建配置文件

      <?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">
      <!-- beans是顶层节点
      可以定义多个bean标签,标签和标签之间没有先后顺序
       -->        
       <!-- 
       id:唯一标识,不能出现特殊字符比如/
       class:控制反转需要的类的全限定类名
       name:名称,理论上可以重复,在实际开发过程中不允许重复
          可以出现特殊字符(/)
          在spring整合struts2时,name属性用于定义该请求的
          urlPattern
        -->
       <bean id="userDao"  class="com.sofwin.dao.impl.UserDaoImpl"></bean>
      </beans>
    • 测试

    package com.sofwin.test;
      
      import org.springframework.context.ApplicationContext;
      import org.springframework.context.support.ClassPathXmlApplicationContext;
      
      import com.sofwin.dao.UserDao;
      
      public class Test01 {
        public static void main(String[] args) {
            // 工厂
            // ClassPathXmlApplicationContext
            // 是基于classpath下的配置文件生成的工厂(配置文件相对于classpath的位置)
            // a.xml
            // FileSystemXmlApplicationContext
            // 基于文件系统中的配置文件生成的工厂对象
            // C:\\A\a.xml
            // 在spring框架下可以出现多个配置文件
            ApplicationContext context =new ClassPathXmlApplicationContext("applicationContext.xml");
            UserDao dao = (UserDao)context.getBean("userDao");//通过name/id来获取对象
            dao.saveUser();
        }
      }
      
      

    面试问题

    ApplicationContext的区别BeanFactory

    1. 都是接口

    2. ApplicatonContex是BeanFactory的子接口

    3. 在单例模式下(默认bean标签使用的是单例)applicationContext在容器创建时,会实例化所有bean。BeanFactory只有在第一次getBean的时候才实例化对象。在多例模式下都是在getBean时实例化对象

1.2 普通bean IOC

<?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">
<!-- beans是顶层节点
可以定义多个bean标签,标签和标签之间没有先后顺序
 -->        
 <!-- 
 id:唯一标识,不能出现特殊字符比如/
 class:控制反转需要的类的全限定类名
 name:名称,理论上可以重复,在实际开发过程中不允许重复
      可以出现特殊字符(/)
      在spring整合struts2时,name属性用于定义该请求的
      urlPattern
 scope:作用域
        默认是singleton 单例
        prototype  多例
        request   每次请求生成一个对象
        session 每次回话生成一个对象
        application
        websocket
  -->
 <bean id="userDao"  class="com.sofwin.dao.impl.UserDaoImpl" scope="prototype" ></bean>
​
</beans>

1.3 静态工厂 Bean IOC

工厂中创建实例的方法是静态方法

<!-- 
 静态方法的调用是类名.方法名
 factory-method:用于指定静态方法的方法名
 虽然class是工厂类型,但是getBean获取的实例应该是factory-method对应的
 方法的返回值类型
  --> 
  <bean id="userDao" class="com.sofwin.util.DaoFactory" factory-method="getUserDao"></bean>
​
package com.sofwin.util;
​
import com.sofwin.dao.UserDao;
import com.sofwin.dao.impl.UserDaoImpl;
​
public class DaoFactory {
    
    public static UserDao getUserDao() {
        return new UserDaoImpl();
    }
    public static UserDao getUserDao2() {
        return new UserDaoImpl();
    }
    public static UserDao getUserDao3() {
        return new UserDaoImpl();
    }
​
}

1.4 实例工厂Bean IOC

工厂中创建实例的方法是普通方法

<!-- 
  实例工厂的IOC需要分2步执行
  1.工厂IOC
   -->
   <bean id="factory" class="com.sofwin.util.DaoFactory">
   </bean>
   <!-- 
   2.指定调用某个工厂对象的某个方法
 factory-bean:用于指定工厂的id
 factory-method
    -->
    <bean id="userDao" factory-bean="factory" factory-method="getUserDao"></bean>

1.5 Bean的生命周期

  • 构造方法执行(实例化时)

  • 初始化方法执行(构造方法执行以后) init-method

  • 销毁方法 destroy-method

1.6 后处理Bean

是spring提供的用于监听容器中对象初始化的Bean。注意:该bean是直接由spring来调用的,不需要指定id,需要实现指定接口BeanPostProcessor

package com.sofwin.util;
​
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
​
public class SofwinBean implements BeanPostProcessor {
​
    /**
     * 初始化方法执行前执行
     * bean:监控到的bean
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println(bean);
        System.out.println(beanName);
        return bean;
    }
    /**
     * 初始化方法执行后执行
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println(bean);
        System.out.println(beanName);
        return bean;
        }
​
}
​
 <bean class="com.sofwin.util.SofwinBean"></bean>
​

1.7 基于annotation的IOC

第一类:用于替换xml中的bean标签 id class

第二类:用于定义生命周期的

注意

需要开启组件扫描,需要添加AOP依赖

<?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">
<!-- 
增加context约束
    1.添加namespace  xmlns:context="http://www.springframework.org/schema/context"
    2.添加约束contxt.xsd
    开启组件扫描
    base-package:指定需要扫描的包
 -->
 <context:component-scan base-package="com.sofwin"></context:component-scan>
</beans>

一下注解都是类级别的注解,用于替换xml中的bean

id :注解中的value属性对应的就是xml中的id,可以不写,类名首字母小写就是id

classpath:注解是类级别的注解

  • @Component(原生态注解)

衍生注解(除了@Controller其余的注解和@Component一样

  • @Controller

  • @Service

  • @Repository

注解适用于开发过程中自定义Bean的处理。xml用于开发中第三方架构的Bean的处理

init-method:@PostConstructor

destroy-method:@PreDestroy

1.8 DI(Dependency injection)

依赖注入必须使用IOC的环境,依赖的双方都必须交给spring管理

extend

has a

use a 依赖

contains a

Class A中用到了Class B的对象b,一般情况下,需要在A的代码中显式的new一个B的对象。

采用依赖注入技术之后,A的代码只需要定义一个私有的B对象,不需要直接new来获得这个对象,而是通过相关的容器控制程序来将B对象在外部new出来并注入到A类里的引用中。而具体获取的方法、对象被获取时的状态由配置文件(如XML)来指定。 [1]

class A{
​
B b;
C c;
​
}
// 不关注A,B,C对象的生成过程(容器来生成的)
// 不关注b的注入过程

1.8.1 基于xml的依赖注入

简单类型的依赖注入

  • setter方法注入

可以属性,并且包含有公有的setter方法的属性依赖注入到对象中

<?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 definitions here -->
<bean id="user" class="com.sofwin.pojo.User">
<!-- 
setter方法注入
name:属性的属性名
value:简单类型的值
ref:引用地址(bean的id),被引用的实体类的bean的id
 -->
 <property name="id" value="100"></property>
 <property name="name" value="100admin"></property>
 <property name="dept" ref="dept"></property>
</bean>
<bean id="dept" class="com.sofwin.pojo.Dept">
    <property name="id" value="110"></property>
    <property name="name" value="deptName"></property>
</bean>
</beans>
Class userClass = Class.forName("");
Object obj = userClass.newInstance();
String methodName ="setId";
Method m = userClass.getDeclaredMethod(methodName,)
m.invoke(obj,100);

  • 构造方法注入

可以重载构造方法,依赖的对象通过构造方法注入

<?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 definitions here -->
<bean id="user" class="com.sofwin.pojo.User">
<!-- 
用于指定构造方法的输入值
name:构造方法中形参名称
type:指定形参类型(可以省略)
index:代表参数的索引  (name二选一)
value:实参
ref
 -->
<constructor-arg index="0" type="java.lang.String" value="100"></constructor-arg>
<constructor-arg index="1" type="java.lang.String" value="admin"></constructor-arg>
</bean>
<bean id="dept" class="com.sofwin.pojo.Dept">
    <property name="id" value="110"></property>
    <property name="name" value="deptName"></property>
</bean>
</beans>

  • P命名空间注入

  1. 在配置文件中构建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:context="http://www.springframework.org/schema/context"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
         http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
    <!-- bean definitions here -->
    <!-- 
    由于p命名空间无法检测属性的类型 
    p:属性名=简单数据类型
    p:属性名-ref=引用数据类型注入
     -->
<bean id="user" class="com.sofwin.pojo.User" p:id="100" p:name="admin" p:dept-ref="dept">
</bean>
<bean id="dept" class="com.sofwin.pojo.Dept">
    <property name="id" value="110"></property>
    <property name="name" value="deptName"></property>
</bean>
</beans>

  • SPEL表达式注入

#{变量}

#{表达式}

#{对象.属性}

   
 <!-- bean definitions here -->
    <!-- 
    由于p命名空间无法检测属性的类型 
    p:属性名=简单数据类型
    p:属性名-ref=引用数据类型注入
     -->
<bean id="user" class="com.sofwin.pojo.User" p:id="#{dept.id}" p:name="admin" p:dept-ref="dept">
</bean>
<bean id="dept" class="com.sofwin.pojo.Dept">
    <property name="id" value="#{T(java.lang.Math).random*100}"></property>
    <property name="name" value="deptName"></property>
</bean>

引用类型的依赖注入

  • setter方法注入

  • 构造方法注入

<?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 definitions here -->
<bean id="user" class="com.sofwin.pojo.User">
<!-- 
用于指定构造方法的输入值
name:构造方法中形参名称
type:指定形参类型(可以省略)
index:代表参数的索引  (name二选一)
value:实参
ref:用于引用的id
 -->
<constructor-arg index="0" ref="dept"></constructor-arg>
</bean>
<bean id="dept" class="com.sofwin.pojo.Dept">
    <property name="id" value="110"></property>
    <property name="name" value="deptName"></property>
</bean>
</beans>

  • P命名空间注入

  • SPEL表达式注入

其他类型的依赖注入

在整合其他第三方架构时,需要使用

  • list

    <!-- 
    用于注入list属性的
     -->
    <list>
    <!-- 
    list中增加简单类型的数据
     -->
        <value>1</value>
        <value>2</value>
        <value>3</value>
    </list>
    
    <!-- 
    用于注入list属性的
     -->
    <list>
    <!-- 
    ref:
    bean用于放引用类型的bean的id
     -->
        <ref bean="dept"/>
        <ref bean="dept"/>
    </list>

  • array

 <array>
            <value>1</value>
            <value>2</value>
            <value>3</value>
            <!-- 
            自定义pojo类型的数组  ref  bean 
             -->
            <ref/>
        </array>

  • properties

注意

.properties配置文件 key=value key和value都 不能使用“” jdbc.userName=root

    <property name="pros">
    <props>
        <prop key="userName">admin</prop>
            <prop key="userName1">admin1</prop>
                <prop key="userName2">admin2</prop>
    </props>
    </property>

  • map

<property name="map">
    <map>
    <!-- 
    一个键值对
    key:简单类型的key
    key-ref:引用类型的key对应的bean id
    value:简单类型的值
    value-ref:引用类型的值对应的bean id
     -->
    <entry key="name" value="admin"></entry>
    <entry key="name1" value-ref="dept"></entry>
    <entry key-ref="dept" value="admin2"></entry>
    <entry key-ref="dept" value-ref="dept"></entry>
    </map>

1.8.2 基于annotation的依赖注入

  1. 开启组件扫描

注解

1. @value

注入简单类型的属性

属性级别:

方法级别

参数级别

package com.sofwin.pojo;
​
import java.util.List;
import java.util.Map;
import java.util.Properties;
​
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class User {
    // 简单类型的属性的依赖注入可以将@Value注解写在
    // 属性中也可以将@Value写在setter方法上
    @Value(value="1000")
    private Integer id;
    @Value(value="admin")
    private String name;
    private Integer age;
    private String pwd;
    
    
    private List<Integer> ids;
    
    private List<Dept> depts;
    
    private Integer[] array;
    
    
    private Properties pros;
    
    private Map map;
    
    private Dept dept;// 用户所属部门
​
    public Map getMap() {
        return map;
    }
​
    
    public void setMap(Map map) {
        this.map = map;
    }
​
​
    public void setDepts(List<Dept> depts) {
        this.depts = depts;
    }
​
​
​
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public String getPwd() {
        return pwd;
    }
    public void setPwd(String pwd) {
        this.pwd = pwd;
    }
    public Dept getDept() {
        return dept;
    }
    public void setDept(Dept dept) {
        this.dept = dept;
    }
​
​
    public List<Integer> getIds() {
        return ids;
    }
​
​
    public void setIds(List<Integer> ids) {
        this.ids = ids;
    }
​
​
    public Integer[] getArray() {
        return array;
    }
​
​
    public void setArray(Integer[] array) {
        this.array = array;
    }
​
​
    public List<Dept> getDepts() {
        return depts;
    }
​
​
    public Properties getPros() {
        return pros;
    }
​
​
    public void setPros(Properties pros) {
        this.pros = pros;
    }
    
    
​
​
}
  1. 按类型注入

@Autowired(自动装配)

// ref
    // 在注入时按照类型注入
    // 容器中不能出现多个同种类型的对象
    @Autowired
    private Dept deptsfd;// 用户所属部门
    
    @Autowired(required = false)
    private UserDao dao;

  1. 按名称注入

@Resource

装配机制:默认按照名称注入(属性名为需要注入的bean的id),如果按名称没有注入成功,按类型注入,并且可以强制使用按什么注入

    // name指定注入的bean的id
    @Resource
    private UserDao userDaoImplsxxx;
​
    

组合注解

@Autowird

@Qualifer

@Autowired
    @Qualifier("userDaoImpl")
    private UserDao userDaoImplsxxx;
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值