Spring基礎(chǔ)

spring簡(jiǎn)介

基礎(chǔ)技術(shù)

  1. java
  2. 反射
  3. xml
  4. xml解析
  5. 代理
  6. 大量設(shè)計(jì)模式

關(guān)鍵在于在容器中獲取對(duì)象,spring默認(rèn)是單例模式

基礎(chǔ)環(huán)境搭建

數(shù)據(jù)庫的操作
<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依賴(有四個(gè)context,core,beans,expression,但是context依賴其他的3種,所以只需要導(dǎo)入context即可)

    <dependency>
              <groupId>org.springframework</groupId>
              <artifactId>spring-context</artifactId>
              <version>5.0.8.RELEASE</version>
    </dependency>
    
  2. 編寫一個(gè)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">
    <!--將對(duì)象的創(chuàng)建交給spring容器,在這個(gè)配置文件中聲明我要什么對(duì)象
        bean標(biāo)簽的class: 寫java類的全限定類名,它是通過全類名然后使用反射技術(shù)進(jìn)行創(chuàng)建的
        bean標(biāo)簽的id:標(biāo)識(shí)符,獲取對(duì)象的時(shí)候使用-->
        <bean class="com.sz.pojo.Girl" id="girl">
            <property name="age" value="10"></property>
            <property name="name" value="頂頂頂頂"></property>
        </bean>
    </beans>
    
  1. 通過spring的應(yīng)用程序上下文對(duì)象獲取對(duì)象
@Test
public void m1(){
        //獲取上下文對(duì)象,spring里面聲明對(duì)象都需要通過上下文對(duì)象獲取
        ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
        Girl girl1 = ctx.getBean("girl", Girl.class);
        System.out.println(girl);
    }

ClassPathXmlApplicationContext()函數(shù)里面可以傳入String數(shù)組,達(dá)到讀取多個(gè)配置文件的目的

核心學(xué)習(xí)內(nèi)容

IOC

  1. 控制反轉(zhuǎn)(inverse of control)也稱依賴注入

    控制:創(chuàng)建對(duì)象 ,彼此關(guān)系的權(quán)利

    反轉(zhuǎn):此權(quán)利交給了spring容器

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

  • setter注入(最常用):

必須其字段有對(duì)應(yīng)setter方法才可以完成name setName();

通過property子節(jié)點(diǎn)完成注入

報(bào)錯(cuò)分析:

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

com.sz.pojo.Girl這個(gè)類必須要有無參構(gòu)造器

  • 構(gòu)造注入:
<!--前提是Girl有構(gòu)造方法public Girl(String name, Integer age) constructor-arg里面的name屬性與構(gòu)造器的參數(shù)匹配-->
<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有構(gòu)造方法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不能被實(shí)例化,只能被繼承

parent:表示該bean繼承于哪個(gè)bean,用id做標(biāo)識(shí)符

init-method:初始化時(shí)自動(dòng)調(diào)用的方法,適合數(shù)據(jù)庫連接,數(shù)據(jù)源的注入

destroy-method:銷毀時(shí)自動(dòng)調(diào)用的方法

lazy-init(true):默認(rèn)容器ctx被實(shí)例化時(shí)就會(huì)去執(zhí)行配置文件applicationContext.xml中里面注冊(cè)了的bean的無參構(gòu)造方法

但是調(diào)用了這個(gè)屬性的bean,會(huì)在調(diào)用bean的時(shí)候才執(zhí)行無參構(gòu)造方法

scope(prototype):調(diào)用該bean聲明的對(duì)象都是不同的,都是新new出來的

scope(singleton):調(diào)用該bean聲明的對(duì)象是相同的,都是同一個(gè),默認(rèn)是這種

depends-on:依賴的bean,如果某一個(gè)bean嚴(yán)重依賴另一個(gè)bean

ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
((ClassPathXmlApplicationContext) ctx).close();
((ClassPathXmlApplicationContext) ctx).refresh();
//這兩個(gè)方法調(diào)用其中之一才會(huì)執(zhí)行destroy-method方法
  1. 子標(biāo)簽分析

    property標(biāo)簽:

    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>
        <!--數(shù)組-->
            <property name="str">
                <array>
                    <value>劉德華</value>
                    <value>郭富城</value>
                </array>
            </property>
        <!--集合-->
            <property name="list">
                <list>
                    <value>1</value>
                    <value>2</value>
                </list>
            </property>
        <!--list集合里面裝dog對(duì)象-->
            <property name="listDog">
                <list>
                    <!--內(nèi)部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對(duì)象-->
        <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>
    

自動(dòng)注入(autowire)

  • byType:按照類型注入,在上下文搜索對(duì)應(yīng)需要的bean(primary="true"默認(rèn)也是true)

    如果該類型有且只有一個(gè),匹配成功

    如果沒有該類型則不注入

    如果超過一個(gè),則報(bào)錯(cuò)

    <!--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對(duì)應(yīng)的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"/>
    <!--這個(gè)標(biāo)簽可以將其他的配置文件引入,這樣的話,我們將來整體讀取這一核心配置文件即可,意思就是要用UserBean.xml里面的bean的話,可以只引入applicationContext.xml-->
 <!--而且classpath:UserBean.xml支持*匹配UserBean-*.xml就會(huì)引入所以"UserBean-"開頭的xml文件-->
    <import resource="classpath:UserBean.xml"/>
    <bean class="com.sz.dao.ProviderDao">
        <!--${}表達(dá)式可以去引用我們引入的這些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,強(qiáng)調(diào)處理控制層)

service(業(yè)務(wù)層)

repository(強(qiáng)調(diào)數(shù)據(jù)訪問層)

四個(gè)注解功能相同

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

AOP(xml版本)

專業(yè)術(shù)語

  1. target:目標(biāo)類,需要被代理的類。例如:UserService
  2. Joinpoint(連接點(diǎn)):所謂連接點(diǎn)是指那些可能被攔截到的方法。例如:所有的方法
  3. PointCut 切入點(diǎn):已經(jīng)被增強(qiáng)的連接點(diǎn)。例如:addUser()
  4. advice 通知/增強(qiáng),增強(qiáng)代碼。例如:after、before
  5. Weaving(織入):是指把增強(qiáng)advice應(yīng)用到目標(biāo)對(duì)象target來創(chuàng)建新的代理對(duì)象proxy的過程.
  6. proxy 代理類
  7. Aspect(切面): 是切入點(diǎn)pointcut和通知advice的結(jié)合

? 一個(gè)線是一個(gè)特殊的面。

? 一個(gè)切入點(diǎn)和一個(gè)通知,組成成一個(gè)特殊的面。

通知

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

? 在目標(biāo)方法執(zhí)行前實(shí)施增強(qiáng)

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

? 在目標(biāo)方法執(zhí)行前實(shí)施增強(qiáng)

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

? 在目標(biāo)方法返回值執(zhí)行后實(shí)施增強(qiáng)

? 環(huán)繞通知 org.aopalliance.intercept.MethodInterceptor(功能最強(qiáng),但是用得少)目標(biāo)方法的調(diào)用由環(huán)繞通知決定,即你可以決定是否調(diào)用目標(biāo)方法,而前置和后置通知 是不能決定的,他們只是在方法的調(diào)用前后執(zhí)行通知而已,即目標(biāo)方法肯定是要執(zhí)行的。

? 在目標(biāo)方法執(zhí)行前后實(shí)施增強(qiáng)

? 異常拋出通知 org.springframework.aop.ThrowsAdvice

? 在方法拋出異常后實(shí)施增強(qiáng)

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

在目標(biāo)類中添加一些新的方法和屬性

切入點(diǎn)表達(dá)式

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

? 語法:execution(修飾符 返回值 包.類.方法名(參數(shù)) 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結(jié)尾

? User* 以User開頭

? * 任意

? 方法名,不能省略

? addUser 固定方法

? add* 以add開頭

? *Do 以Do結(jié)尾

? * 任意

? (參數(shù))

? () 無參

? (int) 一個(gè)整型

? (int ,int) 兩個(gè)

? (..) 參數(shù)任意

? throws ,可省略,一般不寫。

步驟

  1. 額外補(bǔ)充的依賴
<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是基于代理完成的,所以我們要激活我們自動(dòng)代理-->
    <aop:aspectj-autoproxy/>
    <!--目標(biāo)類要在spring中注冊(cè),沒有注冊(cè)不能作為目標(biāo)類-->
    <bean class="com.sz.service.ProviderService" id="providerService">
    </bean>
<!--2.注冊(cè)一個(gè)切面要使用的類-->
    <bean class="com.sz.advice.BeforeAdvice" id="beforeAdvice">
    </bean>
<!--3.配置切面的元素-->
<aop:config>
    <aop:aspect  ref="beforeAdvice">
        <!--aop:before表明它確實(shí)是前置通知(可以有多個(gè)前置通知)
method:指明它使用哪個(gè)方法來切beforeAdvice里面的方法名字
pointcut:切入點(diǎn)
你要什么包下面的什么類下面的什么方法
        -->
        <!--execution(* com.sz.service.ProviderService.*())切無參
           execution(* com.sz.service.ProviderService.*(java.lang.Integer))切一個(gè)參數(shù)是Integer類型的
          execution(* com.sz.service.ProviderService.*(int))切一個(gè)參數(shù)是int類型的
包裝類與基本數(shù)據(jù)類型有嚴(yán)格的區(qū)分
        -->
<aop:before method="methodBefore" pointcut="execution(* com.sz.service.ProviderService.*(..))"></aop:before>
    </aop:aspect>
</aop:config>
</beans>
  1. 測(cè)試
 ApplicationContext ctx=new ClassPathXmlApplicationContext("application.xml");
 ProviderService demo = ctx.getBean("providerService", ProviderService.class);
 demo.add();

AOP(注解)

@order(數(shù)字)注解可以指定before通知的執(zhí)行順序,數(shù)字小的先執(zhí)行(類級(jí)別的注解)

@order(數(shù)字)注解可以指定after通知的執(zhí)行順序,數(shù)字大的先執(zhí)行(類級(jí)別的注解)

package com.sz.advice;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Order(1)//標(biāo)記順序
@Aspect//標(biāo)記為切面
@Component//相對(duì)于在xml中注冊(cè)bean
public class BeforeAdvice {
    @Before("execution(* com.sz.service.*.*(..))")
    public void before(){
        System.out.println("在一個(gè)世紀(jì)以前");
    }
}

常見注解總結(jié)

  1. Configuration:標(biāo)明一個(gè)類為配置類,然后程序啟動(dòng)的時(shí)候只要掃描這個(gè)類,就可以清楚所有的配置規(guī)則
  2. Component:標(biāo)明一個(gè)類為spring的一個(gè)組件,可以被spring容器所管理
  3. Service:同上,語義為服務(wù)層
  4. Repository:同上,語義為Dao層
  5. Controller:同上,語義為控制層
  6. ComponentScan:組件掃描,可以絕對(duì)去掃描哪些包
  7. Bean:用于在spring容器中注冊(cè)一個(gè)Bean
  8. Autowired:自動(dòng)注冊(cè)bean,會(huì)按類型裝配
  9. @Resource默認(rèn)按名稱裝配,如果不到與名稱匹配的bean,會(huì)按類型裝配。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 本來是準(zhǔn)備看一看Spring源碼的。然后在知乎上看到來一個(gè)帖子,說有一群**自己連Spring官方文檔都沒有完全讀...
    此魚不得水閱讀 7,044評(píng)論 4 21
  • 參考W3C Spring教程 Spring致力于J2EE應(yīng)用的各種解決方案,而不僅僅專注于某一層解決方案??梢哉fS...
    王偵閱讀 1,236評(píng)論 0 6
  • 如下是整篇文章的結(jié)構(gòu),所需閱讀時(shí)間大約20min Spring簡(jiǎn)介 Spring框架由Rod Johnson開發(fā),...
    逆風(fēng)飛行1226閱讀 977評(píng)論 0 15
  • 應(yīng)該明白,在這個(gè)世界上,能夠傷害我們最深的人,往往不會(huì)是那些所謂的敵人,而只會(huì)是和我們最親的人。
    楊嘉利閱讀 223評(píng)論 0 3
  • 原計(jì)劃 今天應(yīng)該開始動(dòng)手寫demo的,但是早上開個(gè)同步進(jìn)度的站會(huì),給時(shí)間浪費(fèi)了。下午印度人拉了一個(gè)會(huì)議,然后一直開...
    Billson日拱一卒閱讀 94評(píng)論 0 1

友情鏈接更多精彩內(nèi)容