Spring

快速入门

Spring是一个管理Bean的容器,一个轻量级框架

  • 使用Spring,需要引入对应的依赖下载地址

        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <springFramework.version>5.1.5.RELEASE</springFramework.version>
        </properties> 
      <dependencies>
            <!-- spring相关 -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-web</artifactId>
                <version>${springFramework.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-webmvc</artifactId>
                <version>${springFramework.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>${springFramework.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-jdbc</artifactId>
                <version>${springFramework.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-test</artifactId>
                <version>${springFramework.version}</version>
            </dependency>
            <!--日志-->
            <dependency>
                <groupId>org.apache.logging.log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>2.10.0</version>
            </dependency>
            <dependency>
                <groupId>commons-logging</groupId>
                <artifactId>commons-logging</artifactId>
                <version>1.2</version>
            </dependency>
        </dependencies>
    
  • 管理对象,必须是一个接口一个实现类

    /**
     * 战士
     */
    public interface Fighter {
        void show();
    }
    
    /**
    * 吕布,战士类的一个实现类
    */
    public class LvBu implements Fighter {
        public void show() {
            System.out.println("战士吕布");
        }
    }
    

IOC控制反转/DI依赖注入

回顾历史

之前我们创建对象的方式,是在一个类中主动new另一个类的对象,然后再调用其方法完成功能

public class Main {
    public static void main(String[] args) {
        // 获取对象 -- 以前的方式,主动创建
        Fighter f1 = new LvBu();
        f1.show();
    }
}

Main类掌握着Fighter类型对象的控制权(想创建就创建),这样带来一个缺点,当许多模块都需要使用Fighter类型对象时,一旦Fighter类型对象需要发生改变,需要大量的修改其他模块的代码才能满足需求,所以,Spring提出了一种新的获取对象的方式 -- 配置

spring配置文件

spring.xml

<?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-3.0.xsd">

    <!--配置一个对象-->
    <!--LvBu lvbu = new LvBu();-->
    <bean id="lvbu" class="com.neuedu.test.LvBu"></bean>
    <bean id="guanyu" class="com.neuedu.test.GuanYu"></bean>

</beans>
public class Main {
    public static void main(String[] args) {
        // 获取对象 -- 以前的方式,主动创建
//        Fighter f1 = new LvBu();
//        f1.show();

        // Spring的方式获取对象,需要把对象配置在xml文件中
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        Fighter lvbu = (Fighter)applicationContext.getBean("lvbu");
        Fighter guanyu = (Fighter)applicationContext.getBean("guanyu");
        lvbu.show(); // 战士吕布
        guanyu.show(); // 战士关羽
    }
}

使用配置的方式带来一个好处,当Fighter类型对象需要改变的时候,我们只需要修改spring.xml就可以了,不需要修改其他模块,便利了开发

IOC控制反转

对于java应用程序来说,对象的控制权逆转了,这个概念称为IOC--控制反转。
之间调用或创建对象都是交给java应用程序来完成,现在交给spring来分配。

DI依赖注入

对于spring来说,配置一个对象,相当于对其他调用者注入了一个可调用的对象

IOC控制反转和DI依赖注入没有区别,只是针对参照物不同的不同说法

属性注入
  • 构造器注入(前提:必须有有参构造器)

    <!--默认是调用无参构造器创建对象的,若没有无参构造器,会报错-->
    <bean id="guanyu" class="com.neuedu.test.GuanYu"></bean>
    
    public class GuanYu implements Fighter {
        private String name;
        private int age;
        public GuanYu() {}
        public GuanYu(String name, int age) {
            this.name = name;
            this.age = age;
        }
        public void show() {
            System.out.println(name+","+age);
        }
    }
    
    <!--利用有参构造器进行属性注入-->
    <bean id="guanyu" class="com.neuedu.test.GuanYu">
        <!--构造器注入属性-->
        <!--给对象的name属性,赋值“关羽”-->
        <constructor-arg name="name" value="关羽"></constructor-arg>
        <!--给对象的age属性,赋值14-->
        <constructor-arg name="age" value="14"></constructor-arg>
    </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-3.0.xsd">
        <bean id="guanyu" class="com.neuedu.test.GuanYu">
            <constructor-arg name="name" value="关羽"></constructor-arg>
            <!--属性注入如果是对象,需要用ref关联另一个对象id-->
            <constructor-arg name="weapon" ref="qinglong"></constructor-arg>
        </bean>
        <!--配一个QingLong-->
        <bean id="qinglong" class="com.neuedu.test.QingLong">
            <property name="dps" value="50"></property>
        </bean>
    </beans>
    

    集合

  • setter注入

    <bean id="guanyu" class="com.neuedu.test.GuanYu">
        <!--利用set方法注入属性-->
        <property name="name" value="关羽坤"></property>
        <property name="age" value="144"></property>
    </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-3.0.xsd">
        <bean id="guanyu" class="com.neuedu.test.GuanYu">
            <property name="name" value="关羽"></property>
            <!--属性注入如果是对象,需要用ref关联另一个对象id-->
            <property name="weapon" ref="qinglong"></property>
        </bean>
        <!--配一个QingLong-->
        <bean id="qinglong" class="com.neuedu.test.QingLong">
            <property name="dps" value="50"></property>
        </bean>
    </beans>
    

    集合

        <bean id="guanyu" class="com.neuedu.test.GuanYu">
            <property name="name" value="关羽"></property>
            <!--属性注入如果是对象,需要用ref关联另一个对象id-->
            <property name="weapon" ref="qinglong"></property>
            <!--List<String>-->
            <property name="boy">
                <list>
                    <value>张飞</value>
                    <value>马超</value>
                </list>
            </property>
            <!--List<Weapon>-->
            <property name="repository">
                <list>
                    <ref bean="qinglong"></ref>
                    <ref bean="fang"></ref>
                </list>
            </property>
            <!--Map<String,String>-->
            <property name="horse">
                <map>
                    <entry key="坐骑1" value="赤兔"></entry>
                    <entry key="坐骑2" value="的卢"></entry>
                </map>
            </property>
            <!--Map<String,Weapon>-->
            <property name="weaponMap">
                <map>
                    <entry key="武器1" value-ref="qinglong"></entry>
                    <entry key="武器2" value-ref="fang"></entry>
                </map>
            </property>
        </bean>
    
  • 接口注入(Spring不支持)

自动装配(了解)

<!-- ==========================自动按名字装配autowire=byName=========================== -->
<!-- ==========================自动按类型装配autowire=byType=========================== -->
<bean id="qiyi" class="com.neuedu.test1.QiYi" autowire="byType"/>
<!-- 当按照类型装配时,有多个符合条件的对象,需要指定primary="true"表明是主要的装配对象 -->
<bean id="wuqi" class="com.neuedu.test1.FaZhang" primary="true">
    <property name="name" value="大法师之杖"></property>
</bean>
<bean id="kandao" class="com.neuedu.test1.KanDao">
    <property name="name" value="大法师砍刀"></property>
</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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    <!-- 开启注解 -->
    <context:annotation-config />
    <bean id="guanyu" class="com.neuedu.test.GuanYu"></bean>
    <bean id="abc1" class="com.neuedu.test.QingLong">
        <qualifier value="test1"></qualifier>
    </bean>
    <bean id="abc2" class="com.neuedu.test.Fang">
        <qualifier value="test2"></qualifier>
    </bean>
</beans>
package com.neuedu.test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

public class GuanYu implements Fighter {
    private String name = "关羽";
    @Autowired
    @Qualifier("test2")// 转配的com.neuedu.test.Fang
    private Weapon weapon;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setWeapon(Weapon weapon) {
        this.weapon = weapon;
    }
    public void show() {
        System.out.println(name);
        weapon.showInfo();
    }
}

注解自动装配(重要)

spring.xml配置扫描包

<?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-3.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    <context:component-scan base-package="com.neuedu.test"></context:component-scan>
    <bean id="guanyu" class="com.neuedu.test.GuanYu"></bean>
</beans>
public class Main {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        GuanYu guanyu = (GuanYu)applicationContext.getBean("guanyu");
        guanyu.show();
    }
}
@Component("test1")
public class QingLong implements Weapon {
    private int dps;
    public void setDps(int dps) {
        this.dps = dps;
    }
    public int getDps() {
        return dps;
    }
    public void showInfo() {
        System.out.println("青龙偃月,攻击力很高");
    }
}
@Component("test2")
public class Fang implements Weapon {
    private int dps;
    public void setDps(int dps) {
        this.dps = dps;
    }
    public int getDps() {
        return dps;
    }
    public void showInfo() {
        System.out.println("方天画戟,攻击力很高");
    }
}
@Component
public class GuanYu implements Fighter {
    private String name = "关羽";
    @Autowired
    @Qualifier("test2")
    private Weapon weapon;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setWeapon(Weapon weapon) {
        this.weapon = weapon;
    }
    public void show() {
        System.out.println(name);
        weapon.showInfo();
    }
}

@Component:标记类,交给spring统一管理。(不同层,用的)
@Autowired:注入依赖。
@Qualifier("test2"):注入依赖具体的名字。

类型 说明

@Component 通用的构造型注解,标示该类为Spring 组件。

@Controller 标识将该类定义为Spring MVC controller。

@Repository 标识将该类定义为数据仓库(例如:Dao层)。

@Service 标识将该类定义为服务(例如:Service层)。

AOP面向切面编程

一般应用在如性能检测、访问控制、事务控制、日志记录等

![*](file:///C:\Users\ADMINI~1\AppData\Local\Temp\artD302.tmp)切面(Aspect)

![*](file:///C:\Users\ADMINI~1\AppData\Local\Temp\artD312.tmp)切面是切点和通知组成,通知和切点共同定义了切面的全部内容即:它是什么,在何时何处完成其功能;

![*](file:///C:\Users\ADMINI~1\AppData\Local\Temp\artD313.tmp)连接点(Joinpoint)

![*](file:///C:\Users\ADMINI~1\AppData\Local\Temp\artD314.tmp)连接点是在应用执行过程中能够插入切面的一个点,Spring仅支持方法的连接点,即仅能在方法调用前,方法调用后,方法抛出异常时及方法调用前后插入切面代码。

![*](file:///C:\Users\ADMINI~1\AppData\Local\Temp\artD315.tmp)切点(Pointcut)

![*](file:///C:\Users\ADMINI~1\AppData\Local\Temp\artD316.tmp)切点定义了在何处应用切面,AOP通过“切点”定位特定的连接点。切点相当于查询条件,一个切点可以匹配多个连接点。

![*](file:///C:\Users\ADMINI~1\AppData\Local\Temp\artD317.tmp)通知(Advice)

![*](file:///C:\Users\ADMINI~1\AppData\Local\Temp\artD318.tmp)切面的工作被成为通知,定义了切面是什么及何时使用。除了描述切面要完成的工作,通知还解决了何时执行这个工作的问题,它应该在某个方法被调用之前?之后?等。

![*](file:///C:\Users\ADMINI~1\AppData\Local\Temp\artD319.tmp)Spring切面可以应用5种类型的通知:

![*](file:///C:\Users\ADMINI~1\AppData\Local\Temp\artD32A.tmp)前置通知(Before)在目标方法被调用之前调用通知功能;

![*](file:///C:\Users\ADMINI~1\AppData\Local\Temp\artD32B.tmp)后置通知(After)在目标方法被完成之后调用通知功能,不关心方法的输出是什么;

![*](file:///C:\Users\ADMINI~1\AppData\Local\Temp\artD32C.tmp)环绕通知(Around advice)通知包裹了目标方法,在目标方法调用之前和之后执行自定义的行为;

![*](file:///C:\Users\ADMINI~1\AppData\Local\Temp\artD32D.tmp)异常通知(After-throwing)在目标方法抛出异常后调用通知;

![*](file:///C:\Users\ADMINI~1\AppData\Local\Temp\artD32E.tmp)返回通知(After-returning)在目标方法成功执行之后调用通知;

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353

推荐阅读更多精彩内容