Spring笔记 #01# 一个小而生动的IOC例子代码

例子中仅包含两种类:英雄类Hero和武器类Weapon。

  1. 演示DI:给Hero初始化Weapon
  2. 演示AOP:法师是一个英雄,当他发动攻击的时候需要念咒语,只有咒语正确才能施展魔法。通过定义一个切面来检验咒语的正确性(假设咒语必须要符合某种公共的标准。。。。。)

代码结构:

Spring容器的最小可用依赖

  1. Spring的核心是一个IOC容器,包含两个基础模块:context以及bean(必要)
  2. 添加AspectJ相关依赖用于支持AOP(必要
  3. 添加Log4j依赖方便输出(可选)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>sample</groupId>
    <artifactId>spring</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <!-- -source 1.5 中不支持 try-with-resources-->
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <!-- Use the latest version whenever possible. -->
        <spring.version>5.1.3.RELEASE</spring.version>
        <log4j.version>2.11.1</log4j.version>
        <aspectj.version>1.9.2</aspectj.version>
    </properties>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>${log4j.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>${log4j.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>${aspectj.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>${aspectj.version}</version>
        </dependency>
    </dependencies>
</project>

用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.xsd">
    <import resource="bean/weapons.xml"/>
    <import resource="bean/heroes.xml"/>
</beans>

★子配置文件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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <bean id="mySword" class="sample.spring.iocbasis.weapon.Sword"/>
    <bean id="myMagicBook" class="sample.spring.iocbasis.weapon.MagicBook"/>

    <aop:config>
        <aop:aspect ref="myMagicBook">
            <aop:pointcut id="mageAttack"
                          expression="execution(* sample.spring.iocbasis.hero.Mage.attack(String))" />
            <aop:around pointcut-ref="mageAttack" method="magicLimit" />
        </aop:aspect>
    </aop:config>
</beans>

★子配置文件2,IDEA可能会报错说找不到引用,但其实是Ok的。注意不要重复import一个配置文件,这会导致重复定义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">

    <bean id="iocWarrior" class="sample.spring.iocbasis.hero.Warrior">
        <constructor-arg ref="mySword" />
    </bean>

    <bean id="iocMage" class="sample.spring.iocbasis.hero.Mage">
        <constructor-arg ref="myMagicBook" />
    </bean>
</beans>

实例化容器&使用容器

★程序入口:

package sample.spring.iocbasis;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import sample.spring.iocbasis.hero.Hero;
import sample.spring.iocbasis.hero.Mage;
import sample.spring.iocbasis.hero.Warrior;
import sample.spring.iocbasis.weapon.MagicBook;
import sample.spring.iocbasis.weapon.Sword;

public class MyTest {
    public static void main(String[] args) {
        System.out.println("===========手动调用setter方法注入=================");
        Warrior warrior = new Warrior();
        warrior.attack(null);
        warrior.setWeapon(new Sword());
        warrior.attack(null);

        System.out.println("===========手动调用构造器方法注入=================");
        Warrior warrior2 = new Warrior(new Sword());
        warrior2.attack(null);

        System.out.println("===========直接从IOC容器中获得事先组装好的对象=================");
        ApplicationContext context = new ClassPathXmlApplicationContext("\\spring\\config.xml");
        Warrior iocWarrior = context.getBean("iocWarrior", Warrior.class);
        iocWarrior.attack(null);

        System.out.println("===========通过动态代理增强方法=================");
        Hero iocMage = context.getBean("iocMage", Hero.class);
        iocMage.attack("hello world.");
        iocMage.attack("hlo worl.");

        System.out.println("===========绕过动态代理=================");
        new Mage(new MagicBook()).attack("hlo worl.");
    }
}
/*
===========手动调用setter方法注入=================
Warrior{no=1}用WoodenStick{}发起了一次攻击。
Warrior{no=1}用Sword{no=1}发起了一次攻击。
===========手动调用构造器方法注入=================
Warrior{no=2}用Sword{no=2}发起了一次攻击。
===========直接从IOC容器中获得事先组装好的对象=================
Warrior{no=3}用Sword{no=3}发起了一次攻击。
===========通过动态代理增强方法=================
Mage{no=1}试图发动一次魔法攻击,准备校验咒语【hello world.】正确性 ...
Mage{no=1}用MagicBook{no=1}发起了一次攻击
Mage{no=1}试图发动一次魔法攻击,准备校验咒语【hlo worl.】正确性 ...
Mage{no=1}的咒语念错了,魔法发动失败 ...
===========绕过动态代理=================
Mage{no=2}用MagicBook{no=2}发起了一次攻击
 */

唯一能看出“第三方依赖痕迹”的类:

package sample.spring.iocbasis.weapon;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;

public class MagicBook implements Weapon {

    private static final Logger LOGGER = LogManager.getLogger();

    private static int count = 0;

    private int no = ++count;

    @Override
    public void attack() {

    }

    public void magicLimit(ProceedingJoinPoint jp) {
        try {
            Object obj = jp.getThis();
            String spell = String.valueOf(jp.getArgs()[0]);
            LOGGER.info("{}试图发动一次魔法攻击,准备校验咒语【{}】正确性 ...", obj, spell);
            if ("hello world.".equals(spell)) {
                jp.proceed();
            } else {
                LOGGER.info("{}的咒语念错了,魔法发动失败 ...", obj);
            }
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
    }

    @Override
    public String toString() {
        return "MagicBook{" +
                "no=" + no +
                '}';
    }
}

其它类:

package sample.spring.iocbasis.hero;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import sample.spring.iocbasis.weapon.Weapon;
import sample.spring.iocbasis.weapon.WoodenStick;

public class Warrior implements Hero {

    private static final Logger LOGGER = LogManager.getLogger();

    private static int count = 0;

    private int no = ++count;

    private Weapon weapon;

    public Warrior() {
        weapon = new WoodenStick();
    }

    public Warrior(Weapon weapon) {
        this.weapon = weapon;
    }

    public void setWeapon(Weapon weapon) {
        this.weapon = weapon;
    }

    @Override
    public void attack(String sth) {
        LOGGER.info("{}用{}发起了一次攻击。", this, weapon);
        weapon.attack();
    }

    @Override
    public String toString() {
        return "Warrior{" +
                "no=" + no +
                '}';
    }
}
Warrior.java
package sample.spring.iocbasis.hero;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import sample.spring.iocbasis.weapon.Weapon;

public class Mage implements Hero {

    private static final Logger LOGGER = LogManager.getLogger();

    private static int count = 0;

    private int no = ++count;

    private Weapon weapon;

    public Mage(Weapon weapon) {
        this.weapon = weapon;
    }

    @Override
    public void attack(String spell) {
        LOGGER.info("{}用{}发起了一次攻击", this, weapon);
    }

    @Override
    public String toString() {
        return "Mage{" +
                "no=" + no +
                '}';
    }
}
Mage.java
package sample.spring.iocbasis.weapon;

public class Sword implements Weapon {

    private static int count = 0;

    private int no = ++count;

    @Override
    public void attack() {
    }

    @Override
    public String toString() {
        return "Sword{" +
                "no=" + no +
                '}';
    }
}
Sword.java
package sample.spring.iocbasis.weapon;

public class WoodenStick implements Weapon {
    @Override
    public void attack() {
    }

    @Override
    public String toString() {
        return "WoodenStick{}";
    }
}
WoodenStick.java
package sample.spring.iocbasis.hero;

public interface Hero {

    void attack(String sth);
}
Hero.java

 

posted @ 2019-01-26 18:06  xkfx  阅读(244)  评论(0编辑  收藏  举报