Spring基础

spring简介

基础技术

  1. java
  2. 反射
  3. xml
  4. xml解析
  5. 代理
  6. 大量设计模式

关键在于在容器中获取对象,spring默认是单例模式

基础环境搭建

数据库的操作
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>8.0.13</version>
</dependency>
<dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-tx</artifactId>
          <version>5.0.8.RELEASE</version>
</dependency>
<dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-jdbc</artifactId>
          <version>5.0.8.RELEASE</version>
      </dependency>
<!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
<dependency>
    <groupId>com.mchange</groupId>
    <artifactId>c3p0</artifactId>
    <version>0.9.5.2</version>
</dependency>

  1. 添加spring依赖(有四个context,core,beans,expression,但是context依赖其他的3种,所以只需要导入context即可)

    <dependency>
              <groupId>org.springframework</groupId>
              <artifactId>spring-context</artifactId>
              <version>5.0.8.RELEASE</version>
    </dependency>
    
  2. 编写一个spring的配置文件(放在resources下)

    <?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容器,在这个配置文件中声明我要什么对象
        bean标签的class: 写java类的全限定类名,它是通过全类名然后使用反射技术进行创建的
        bean标签的id:标识符,获取对象的时候使用-->
        <bean class="com.sz.pojo.Girl" id="girl">
            <property name="age" value="10"></property>
            <property name="name" value="顶顶顶顶"></property>
        </bean>
    </beans>
    
  1. 通过spring的应用程序上下文对象获取对象
@Test
public void m1(){
        //获取上下文对象,spring里面声明对象都需要通过上下文对象获取
        ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
        Girl girl1 = ctx.getBean("girl", Girl.class);
        System.out.println(girl);
    }

ClassPathXmlApplicationContext()函数里面可以传入String数组,达到读取多个配置文件的目的

核心学习内容

IOC

  1. 控制反转(inverse of control)也称依赖注入

    控制:创建对象 ,彼此关系的权利

    反转:此权利交给了spring容器

  2. spring的配置文件值的注入:

  • setter注入(最常用):

必须其字段有对应setter方法才可以完成name setName();

通过property子节点完成注入

报错分析:

No default constructor found; nested exception is java.lang.NoSuchMethodException: com.sz.pojo.Girl.<init>()

com.sz.pojo.Girl这个类必须要有无参构造器

  • 构造注入:
<!--前提是Girl有构造方法public Girl(String name, Integer age) constructor-arg里面的name属性与构造器的参数匹配-->
<bean class="com.sz.pojo.Girl" id="girl_demo">
        <constructor-arg name="name" value="wc"></constructor-arg>
        <constructor-arg name="age" value="10"></constructor-arg>
</bean>
<!--前提是Girl有构造方法public Girl(String name)-->
<bean class="com.sz.pojo.Girl" id="girl_demo">
        <constructor-arg name="name" value="wc"></constructor-arg>
</bean>

bean分析

  1. 属性分析

abstract(true):表示该bean不能被实例化,只能被继承

parent:表示该bean继承于哪个bean,用id做标识符

init-method:初始化时自动调用的方法,适合数据库连接,数据源的注入

destroy-method:销毁时自动调用的方法

lazy-init(true):默认容器ctx被实例化时就会去执行配置文件applicationContext.xml中里面注册了的bean的无参构造方法

但是调用了这个属性的bean,会在调用bean的时候才执行无参构造方法

scope(prototype):调用该bean声明的对象都是不同的,都是新new出来的

scope(singleton):调用该bean声明的对象是相同的,都是同一个,默认是这种

depends-on:依赖的bean,如果某一个bean严重依赖另一个bean

ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
((ClassPathXmlApplicationContext) ctx).close();
((ClassPathXmlApplicationContext) ctx).refresh();
//这两个方法调用其中之一才会执行destroy-method方法
  1. 子标签分析

    property标签:

    name(javabean的属性),value(字面值可以表示的),ref(字面值无法表示的)

    <bean class="com.sz.pojo.Girl" id="girl">
    <property name="age" value="10"></property>
            <property name="name" value="你"></property>
            <property name="dog" ref="dog"></property>
        </bean>
       <bean class="com.sz.pojo.Dog" id="dog">
       </bean> 
    

    其他类型

    <bean class="com.sz.pojo.Girl" id="girl">
            <property name="age" value="10"></property>
            <property name="name" value="你"></property>
            <property name="dog" ref="dog"></property>
        <!--数组-->
            <property name="str">
                <array>
                    <value>刘德华</value>
                    <value>郭富城</value>
                </array>
            </property>
        <!--集合-->
            <property name="list">
                <list>
                    <value>1</value>
                    <value>2</value>
                </list>
            </property>
        <!--list集合里面装dog对象-->
            <property name="listDog">
                <list>
                    <!--内部bean无法被外部引用-->
                    <bean class="com.sz.pojo.Dog">
                        <property name="name" value="good boy"></property>
                    </bean>
                    <bean class="com.sz.pojo.Dog">
                        <property name="name" value="good girl"></property>
                    </bean>
                </list>
            </property>
        <!--map集合里面装dog对象-->
        <property name="mapDog">
            <map>
            <entry key="dog1">
                <bean class="com.sz.pojo.Dog">
                        <property name="name" value="good boy"></property>
                </bean>
            </entry>
            <entry key="dog2">
                <bean class="com.sz.pojo.Dog">
                        <property name="name" value="good boy"></property>
                </bean>
            </entry>
            </map>
        </property>
        </bean>
    

自动注入(autowire)

  • byType:按照类型注入,在上下文搜索对应需要的bean(primary="true"默认也是true)

    如果该类型有且只有一个,匹配成功

    如果没有该类型则不注入

    如果超过一个,则报错

    <!--User类里面有类型为Dog的属性-->
    <bean class="com.sz.pojo.User" id="user" autowire="byType">
    </bean>
        <bean class="com.sz.pojo.Dog">
        <property name="name" value="my Dog"></property>
    </bean>
    
  • byName:按照javabean对应的pojo里面的属性名来匹配

    <!--User类里面有类型为Dog的属性,且属性名为dog-->
    <bean class="com.sz.pojo.User" id="user" autowire="byName">
    </bean>
        <bean class="com.sz.pojo.Dog" id="dog">
        <property name="name" value="my Dog"></property>
        </bean>
    

    下面的了解即可,用处不大

  • byConstructor

  • default

  • no

引入外部文件

applicationContext.xml中:
<!--通过这种方式引入类路径下的文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>
    <!--这个标签可以将其他的配置文件引入,这样的话,我们将来整体读取这一核心配置文件即可,意思就是要用UserBean.xml里面的bean的话,可以只引入applicationContext.xml-->
 <!--而且classpath:UserBean.xml支持*匹配UserBean-*.xml就会引入所以"UserBean-"开头的xml文件-->
    <import resource="classpath:UserBean.xml"/>
    <bean class="com.sz.dao.ProviderDao">
        <!--${}表达式可以去引用我们引入的这些properties里面的属性的值通过他的键名来得到值-->
        <property name="driver" value="${driver}"/>
        <property name="url" value="${url}"/>
        <property name="user" value="${username}"/>
        <property name="password" value="${password}"/>
    </bean>

常用注解

component

controller(springmvc,强调处理控制层)

service(业务层)

repository(强调数据访问层)

四个注解功能相同

  1. 注解里面的userService就是bean的id
package com.sz.service;
@Component("userService")
public class UserService {
    public void eat(){
        System.out.println("吃了");
    }
}
  1. 注册com.sz.service下的有@Component注解的bean
application.xml中:
<!--扫描该包以及所有子包-->
<context:component-scan base-package="com.sz.service"/>

AOP(xml版本)

专业术语

  1. target:目标类,需要被代理的类。例如:UserService
  2. Joinpoint(连接点):所谓连接点是指那些可能被拦截到的方法。例如:所有的方法
  3. PointCut 切入点:已经被增强的连接点。例如:addUser()
  4. advice 通知/增强,增强代码。例如:after、before
  5. Weaving(织入):是指把增强advice应用到目标对象target来创建新的代理对象proxy的过程.
  6. proxy 代理类
  7. Aspect(切面): 是切入点pointcut和通知advice的结合

​ 一个线是一个特殊的面。

​ 一个切入点和一个通知,组成成一个特殊的面。

通知

• 前置通知 org.springframework.aop.MethodBeforeAdvice

• 在目标方法执行前实施增强

• 后置通知 org.springframework.aop.MethodAfterAdvice

• 在目标方法执行前实施增强

• 后置返回通知 org.springframework.aop.AfterReturningAdvice

• 在目标方法返回值执行后实施增强

• 环绕通知 org.aopalliance.intercept.MethodInterceptor(功能最强,但是用得少)目标方法的调用由环绕通知决定,即你可以决定是否调用目标方法,而前置和后置通知 是不能决定的,他们只是在方法的调用前后执行通知而已,即目标方法肯定是要执行的。

• 在目标方法执行前后实施增强

• 异常抛出通知 org.springframework.aop.ThrowsAdvice

• 在方法抛出异常后实施增强

• 引介通知 org.springframework.aop.IntroductionInterceptor

在目标类中添加一些新的方法和属性

切入点表达式

1.execution() 用于描述方法 【掌握】

​ 语法:execution(修饰符 返回值 包.类.方法名(参数) throws异常)

​ 修饰符,一般省略

​ public 公共方法

​ * 任意

​ 返回值,不能省略

​ void 返回没有值

​ String 返回值字符串

​ * 任意

​ 包,[省略]

​ com.itheima.crm 固定包

​ com.itheima.crm.*.service com包下面子包任意 (例如:com.itheima.crm.staff.service)

​ com.itheima.crm.. com包下面的所有子包(含自己)

​ com.itheima.crm.*.service.. com包下面任意子包,固定目录service,service目录任意包

​ 类,[省略]

​ UserServiceImpl 指定类

​ *Impl 以Impl结尾

​ User* 以User开头

​ * 任意

​ 方法名,不能省略

​ addUser 固定方法

​ add* 以add开头

​ *Do 以Do结尾

​ * 任意

​ (参数)

​ () 无参

​ (int) 一个整型

​ (int ,int) 两个

​ (..) 参数任意

​ throws ,可省略,一般不写。

步骤

  1. 额外补充的依赖
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>1.9.2</version>
</dependency>
  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:aop="http://www.springframework.org/schema/aop"
       xmlns:c="http://www.springframework.org/schema/c"
       xmlns:cache="http://www.springframework.org/schema/cache"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:jee="http://www.springframework.org/schema/jee"
       xmlns:lang="http://www.springframework.org/schema/lang"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:task="http://www.springframework.org/schema/task"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
        http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd">
<!--1.aop是基于代理完成的,所以我们要激活我们自动代理-->
    <aop:aspectj-autoproxy/>
    <!--目标类要在spring中注册,没有注册不能作为目标类-->
    <bean class="com.sz.service.ProviderService" id="providerService">
    </bean>
<!--2.注册一个切面要使用的类-->
    <bean class="com.sz.advice.BeforeAdvice" id="beforeAdvice">
    </bean>
<!--3.配置切面的元素-->
<aop:config>
    <aop:aspect  ref="beforeAdvice">
        <!--aop:before表明它确实是前置通知(可以有多个前置通知)
method:指明它使用哪个方法来切beforeAdvice里面的方法名字
pointcut:切入点
你要什么包下面的什么类下面的什么方法
        -->
        <!--execution(* com.sz.service.ProviderService.*())切无参
           execution(* com.sz.service.ProviderService.*(java.lang.Integer))切一个参数是Integer类型的
          execution(* com.sz.service.ProviderService.*(int))切一个参数是int类型的
包装类与基本数据类型有严格的区分
        -->
<aop:before method="methodBefore" pointcut="execution(* com.sz.service.ProviderService.*(..))"></aop:before>
    </aop:aspect>
</aop:config>
</beans>
  1. 测试
 ApplicationContext ctx=new ClassPathXmlApplicationContext("application.xml");
 ProviderService demo = ctx.getBean("providerService", ProviderService.class);
 demo.add();

AOP(注解)

@order(数字)注解可以指定before通知的执行顺序,数字小的先执行(类级别的注解)

@order(数字)注解可以指定after通知的执行顺序,数字大的先执行(类级别的注解)

package com.sz.advice;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Order(1)//标记顺序
@Aspect//标记为切面
@Component//相对于在xml中注册bean
public class BeforeAdvice {
    @Before("execution(* com.sz.service.*.*(..))")
    public void before(){
        System.out.println("在一个世纪以前");
    }
}

常见注解总结

  1. Configuration:标明一个类为配置类,然后程序启动的时候只要扫描这个类,就可以清楚所有的配置规则
  2. Component:标明一个类为spring的一个组件,可以被spring容器所管理
  3. Service:同上,语义为服务层
  4. Repository:同上,语义为Dao层
  5. Controller:同上,语义为控制层
  6. ComponentScan:组件扫描,可以绝对去扫描哪些包
  7. Bean:用于在spring容器中注册一个Bean
  8. Autowired:自动注册bean,会按类型装配
  9. @Resource默认按名称装配,如果不到与名称匹配的bean,会按类型装配。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,331评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,372评论 3 398
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,755评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,528评论 1 296
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,526评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,166评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,768评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,664评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,205评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,290评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,435评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,126评论 5 349
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,804评论 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,276评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,393评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,818评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,442评论 2 359

推荐阅读更多精彩内容

  • 本来是准备看一看Spring源码的。然后在知乎上看到来一个帖子,说有一群**自己连Spring官方文档都没有完全读...
    此鱼不得水阅读 6,937评论 4 21
  • 参考W3C Spring教程 Spring致力于J2EE应用的各种解决方案,而不仅仅专注于某一层解决方案。可以说S...
    王侦阅读 1,172评论 0 6
  • 如下是整篇文章的结构,所需阅读时间大约20min Spring简介 Spring框架由Rod Johnson开发,...
    李序锴阅读 899评论 0 15
  • 应该明白,在这个世界上,能够伤害我们最深的人,往往不会是那些所谓的敌人,而只会是和我们最亲的人。
    杨嘉利阅读 204评论 0 3
  • 原计划 今天应该开始动手写demo的,但是早上开个同步进度的站会,给时间浪费了。下午印度人拉了一个会议,然后一直开...
    Billson日拱一卒阅读 63评论 0 1