Spring 基于Introduction的引入

简介: Spring 基于Introduction的引入

在spring里面,引入了非常受大众所熟悉的Introduction,这里将会有一个模拟超市过节里面进行商品打折优惠活动时,该如何进行商品的优惠价格控制案例。


由于只是模拟而已,所以数据库方面暂时只是考虑用模拟的数据进行操控。核心部分在于如何引入introduction。


package com.sise.lh.lab05Test.model;
/**
 * 作者:idea
 * 时间:2017/10/11
 * 使用说明:商品类
 */
public class Goods {
    private int G_id; //商品编号
    private  String G_name;  //商品名称
    private double G_price; //商品单价
    private int G_quantity;  //商品数量
    public int getG_id() {
        return G_id;
    }
    public void setG_id(int g_id) {
        G_id = g_id;
    }
    public String getG_name() {
        return G_name;
    }
    public void setG_name(String g_name) {
        G_name = g_name;
    }
    public double getG_price() {
        return G_price;
    }
    public void setG_price(double g_price) {
        G_price = g_price;
    }
    public int getG_quantity() {
        return G_quantity;
    }
    public void setG_quantity(int g_quantity) {
        G_quantity = g_quantity;
    }
}
复制代码


package com.sise.lh.lab05Test.model;
/**
 * 作者:idea
 * 时间:2017/10/11
 * 使用说明:用户类
 */
public class User {
    private int uid;
    private String uname;
    private String Level; //用户的级别
    public int getUid() {
        return uid;
    }
    public void setUid(int uid) {
        this.uid = uid;
    }
    public String getUname() {
        return uname;
    }
    public void setUname(String uname) {
        this.uname = uname;
    }
    public String getLevel() {
        return Level;
    }
    public void setLevel(String level) {
        Level = level;
    }
}
复制代码


package com.sise.lh.lab05Test.model;
import com.sise.lh.lab05Test.IPay.Amount;
import java.util.List;
/**
 * 作者:idea
 * 时间:2017/10/11
 * 使用说明:购物凭据类
 */
public class Compute_Price implements Amount {
    private int uid;
    private int goods_id; //购买清单的编号
    private List<Goods> goodsList;
    public double pay_all(){    //计算总价格
        double total=0;
//        在这里添加需要实现的代码
        for (Goods good:goodsList) {
            total+=good.getG_price();
        }
        return total;
    }
    public int getUid() {
        return uid;
    }
    public void setUid(int uid) {
        this.uid = uid;
    }
    public int getGoods_id() {
        return goods_id;
    }
    public void setGoods_id(int goods_id) {
        this.goods_id = goods_id;
    }
    public List<Goods> getGoodsList() {
        return goodsList;
    }
    public void setGoodsList(List<Goods> goodsList) {
        this.goodsList = goodsList;
    }
}
复制代码


package com.sise.lh.lab05Test.IPay;
public interface Amount{
        double pay_all();  //支付接口
}
复制代码


package com.sise.lh.lab05Test.Dao;
import com.sise.lh.lab05Test.model.Goods;
import com.sise.lh.lab05Test.model.User;
import java.util.HashMap;
import java.util.Map;
/**
 * 作者:idea
 * 时间:2017/10/11
 * 使用说明:模拟数据库
 */
public class MockDataBase {
    public static Map<Integer,Goods> goodsMap=new HashMap<>();
    public static Map<Integer,User> userMap=new HashMap<>();
    //模拟数据库初始化操作
    static{
        initUsers();
        initGoods();
    }
    public static void initGoods(){
        Goods goods= new Goods();
        goods.setG_id(1002);
        goods.setG_name("冰红茶");
        goods.setG_price(3.5);
        goods.setG_quantity(200);
        Goods goods02= new Goods();
        goods02.setG_id(1003);
        goods02.setG_name("清风纸巾");
        goods02.setG_price(19.5);
        goods02.setG_quantity(200);
        goodsMap.put(10001,goods);
        goodsMap.put(10002,goods02);
    }
    public static void initUsers(){
        User user= new User();
        user.setLevel("vip");
        user.setUname("小明");
        user.setUid(10086);
        User user02= new User();
        user02.setLevel("普通用户");
        user02.setUname("小王");
        user02.setUid(10087);
        userMap.put(user.getUid(),user);
        userMap.put(user02.getUid(),user02);
    }
}
复制代码


以上便是model层的3个bean和一个模拟的支付接口以及一个模拟的数据库

接下来便是服务层的内容:


package com.sise.lh.lab05Test.service;
import com.sise.lh.lab05Test.model.Compute_Price;
import com.sise.lh.lab05Test.model.Goods;
import com.sise.lh.lab05Test.model.User;
import java.util.List;
/**
 * 作者:idea
 * 时间:2017/10/11
 * 使用说明:客户付款服务
 */
public class PayService {
    //模拟数据库情况
    public Compute_Price Pay(User user,List<Goods> goodsList){
        Compute_Price compute_price=new Compute_Price();
        compute_price.setGoods_id(1001675);
        compute_price.setGoodsList(goodsList);
        compute_price.setUid(user.getUid());
        return compute_price;
    }
    //打印订单内容
    public void printOrderList(Compute_Price compute_price){
        System.out.println("顾客id:"+compute_price.getUid());
        System.out.println("商品票据单号"+compute_price.getGoods_id());
        List<Goods> goodsList=compute_price.getGoodsList();
        for (Goods good:goodsList) {
            System.out.println("商品编号 :"+good.getG_id());
            System.out.println("名称 : "+good.getG_name());
            System.out.println("价格 : "+good.getG_price());
        }
        System.out.println("总价"+compute_price.pay_all());
    }
}
复制代码


使用spring所提供的IntroductionInterception拦截器的时候,需要对其进行相应的新接口的引入:


这个时候,我们可以引入一个打折的接口:


package com.sise.lh.lab05Test.IPay;
import com.sise.lh.lab05Test.model.Compute_Price;
/**
 * 作者:idea
 * 时间:2017/10/11
 * 使用说明:商品打折
 */
public interface Discount {
    double discount(Compute_Price cp);
}
复制代码


这个时候就到了引入IntroductionInterception拦截器的时候了:


package com.sise.lh.lab05Test.aop;
import com.sise.lh.lab05Test.IPay.Discount;
import com.sise.lh.lab05Test.model.Compute_Price;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.IntroductionInterceptor;
import java.text.DecimalFormat;
/**
 * 作者:idea
 * 时间:2017/10/11
 * 使用说明:切面口处
 */
public class OtherIntroduction implements IntroductionInterceptor,Discount {
    //判断调用的方法是否为指定类中的方法
    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        if(implementsInterface(methodInvocation.getMethod().getDeclaringClass())){
            return methodInvocation.getMethod().invoke(this,methodInvocation.getArguments());
        }
        return methodInvocation.proceed();
    }
    @Override
    public boolean implementsInterface(Class<?> aClass) {
        return aClass.isAssignableFrom(Discount.class);
    }
    @Override
    public double discount(Compute_Price cp) {
        System.out.println("-----------------------");
        double count=cp.pay_all();
        DecimalFormat df= new DecimalFormat("######0.00");  //精确到小数点后两位数字
        if(count>100){
            System.out.println("优惠活动期间,满100消费即返20的优惠券!");
        }
        if(cp.getUid()==10086){//如果用户是vip用户
            count=count*0.7;
            System.out.println("打折之后,价格是:"+df.format(count));
        }else{ //如果用户不是vip
            count=count*0.9;
            System.out.println("今日优惠,价格是:"+df.format(count));
        }
        return 0;
    }
}
复制代码


最后便是我们的测试类了:


package com.sise.lh.lab05Test.Test;
import com.sise.lh.lab05Test.Dao.MockDataBase;
import com.sise.lh.lab05Test.IPay.Amount;
import com.sise.lh.lab05Test.IPay.Discount;
import com.sise.lh.lab05Test.model.Compute_Price;
import com.sise.lh.lab05Test.model.Goods;
import com.sise.lh.lab05Test.model.User;
import com.sise.lh.lab05Test.service.PayService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
 * 作者:idea
 * 时间:2017/10/11
 * 使用说明:测试类
 */
public class Test {
    //模拟场景,还未进入打折优惠活动期间
    public void MockNotDisCount(){
        PayService payService=new PayService();
        Map<Integer,Goods> goodsMap= MockDataBase.goodsMap;
        Map<Integer,User> userMap= MockDataBase.userMap;
        //模拟获取两件商品
        Goods goods=goodsMap.get(10001);
        Goods goods02=goodsMap.get(10002);
        //模拟用户
        User user=userMap.get(10086);
        List<Goods> goodsList=new ArrayList<Goods>();
        goodsList.add(goods);
        goodsList.add(goods02);
        //模拟付款
        Compute_Price cp=new Compute_Price();
        cp.setGoodsList(goodsList);
        cp=payService.Pay(user,goodsList);
        //打印凭据
        payService.printOrderList(cp);
    }
    //模拟场景,已经进入打折优惠活动期间
    public void MockDisCount(){
        ApplicationContext context= new ClassPathXmlApplicationContext("Test/aop-introduction.xml");
        Amount amount= (Amount) context.getBean("proxyFactorBean");
        PayService payService=new PayService();
        Map<Integer,Goods> goodsMap= MockDataBase.goodsMap;
        Map<Integer,User> userMap= MockDataBase.userMap;
        //模拟获取两件商品
        Goods goods=goodsMap.get(10001);
        Goods goods02=goodsMap.get(10002);
        //模拟用户
        User user=userMap.get(10086);
        List<Goods> goodsList=new ArrayList<Goods>();
        goodsList.add(goods);
        goodsList.add(goods02);
        //模拟付款
        Compute_Price cp=new Compute_Price();
        cp.setGoodsList(goodsList);
        cp=payService.Pay(user,goodsList);
        //打印凭据
        payService.printOrderList(cp);
        ((Discount)amount).discount(cp);
    }
    public static void main(String[] args) {
        Test test=new Test();
        test.MockNotDisCount();
        System.out.println("--------------------------------------------");
        test.MockDisCount();
    }
}
复制代码


相应的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">
    <!--对于bean的初始化申明-->
    <bean id="compute_price" class="com.sise.lh.lab05Test.model.Compute_Price"></bean>
    <bean id="otherIntroduction" class="com.sise.lh.lab05Test.aop.OtherIntroduction"></bean>
    <!--给定相应的实例,并且在初始化的时候进行构造函数里面的注入申明-->
    <bean id="otherAdvice" class="org.springframework.aop.support.DefaultIntroductionAdvisor" >
        <constructor-arg ref="otherIntroduction"></constructor-arg>
        <constructor-arg value="com.sise.lh.lab05Test.IPay.Discount"></constructor-arg>
    </bean>
    <!--代理工厂-->
    <bean id="proxyFactorBean" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="proxyInterfaces" value="com.sise.lh.lab05Test.IPay.Amount"></property>
        <property name="target" ref="compute_price"></property>
        <property name="interceptorNames">
            <list>
                <value>otherAdvice</value>
            </list>
        </property>
    </bean>
</beans>
复制代码


最终的结果如下:


网络异常,图片无法展示
|

目录
相关文章
|
4月前
|
Java Spring 容器
SpringBoot自动配置的原理是什么?
Spring Boot自动配置核心在于@EnableAutoConfiguration注解,它通过@Import导入配置选择器,加载META-INF/spring.factories中定义的自动配置类。这些类根据@Conditional系列注解判断是否生效。但Spring Boot 3.0后已弃用spring.factories,改用新格式的.imports文件进行配置。
879 0
|
5月前
|
人工智能 Java 测试技术
Spring Boot 集成 JUnit 单元测试
本文介绍了在Spring Boot中使用JUnit 5进行单元测试的常用方法与技巧,包括添加依赖、编写测试类、使用@SpringBootTest参数、自动装配测试模块(如JSON、MVC、WebFlux、JDBC等),以及@MockBean和@SpyBean的应用。内容实用,适合Java开发者参考学习。
620 0
|
1月前
|
JavaScript Java Maven
【SpringBoot(二)】带你认识Yaml配置文件类型、SpringMVC的资源访问路径 和 静态资源配置的原理!
SpringBoot专栏第二章,从本章开始正式进入SpringBoot的WEB阶段开发,本章先带你认识yaml配置文件和资源的路径配置原理,以方便在后面的文章中打下基础
271 3
|
1月前
|
Java 测试技术 数据库连接
【SpringBoot(四)】还不懂文件上传?JUnit使用?本文带你了解SpringBoot的文件上传、异常处理、组件注入等知识!并且带你领悟JUnit单元测试的使用!
Spring专栏第四章,本文带你上手 SpringBoot 的文件上传、异常处理、组件注入等功能 并且为你演示Junit5的基础上手体验
822 2
|
8月前
|
前端开发 Java 数据库
微服务——SpringBoot使用归纳——Spring Boot集成Thymeleaf模板引擎——Thymeleaf 介绍
本课介绍Spring Boot集成Thymeleaf模板引擎。Thymeleaf是一款现代服务器端Java模板引擎,支持Web和独立环境,可实现自然模板开发,便于团队协作。与传统JSP不同,Thymeleaf模板可以直接在浏览器中打开,方便前端人员查看静态原型。通过在HTML标签中添加扩展属性(如`th:text`),Thymeleaf能够在服务运行时动态替换内容,展示数据库中的数据,同时兼容静态页面展示,为开发带来灵活性和便利性。
392 0
|
8月前
|
XML Java 数据库连接
微服务——SpringBoot使用归纳——Spring Boot集成MyBatis——基于 xml 的整合
本教程介绍了基于XML的MyBatis整合方式。首先在`application.yml`中配置XML路径,如`classpath:mapper/*.xml`,然后创建`UserMapper.xml`文件定义SQL映射,包括`resultMap`和查询语句。通过设置`namespace`关联Mapper接口,实现如`getUserByName`的方法。Controller层调用Service完成测试,访问`/getUserByName/{name}`即可返回用户信息。为简化Mapper扫描,推荐在Spring Boot启动类用`@MapperScan`注解指定包路径避免逐个添加`@Mapper`
453 0
|
8月前
|
Java 测试技术 微服务
微服务——SpringBoot使用归纳——Spring Boot中的项目属性配置——少量配置信息的情形
本课主要讲解Spring Boot项目中的属性配置方法。在实际开发中,测试与生产环境的配置往往不同,因此不应将配置信息硬编码在代码中,而应使用配置文件管理,如`application.yml`。例如,在微服务架构下,可通过配置文件设置调用其他服务的地址(如订单服务端口8002),并利用`@Value`注解在代码中读取这些配置值。这种方式使项目更灵活,便于后续修改和维护。
151 0
|
8月前
|
SQL Java 数据库连接
微服务——SpringBoot使用归纳——Spring Boot使用slf4j进行日志记录—— application.yml 中对日志的配置
在 Spring Boot 项目中,`application.yml` 文件用于配置日志。通过 `logging.config` 指定日志配置文件(如 `logback.xml`),实现日志详细设置。`logging.level` 可定义包的日志输出级别,例如将 `com.itcodai.course03.dao` 包设为 `trace` 级别,便于开发时查看 SQL 操作。日志级别从高到低为 ERROR、WARN、INFO、DEBUG,生产环境建议调整为较高级别以减少日志量。本课程采用 yml 格式,因其层次清晰,但需注意格式要求。
798 0
|
4月前
|
缓存 JSON 前端开发
第07课:Spring Boot集成Thymeleaf模板引擎
第07课:Spring Boot集成Thymeleaf模板引擎
517 0
第07课:Spring Boot集成Thymeleaf模板引擎
|
8月前
|
缓存 NoSQL Java
基于SpringBoot的Redis开发实战教程
Redis在Spring Boot中的应用非常广泛,其高性能和灵活性使其成为构建高效分布式系统的理想选择。通过深入理解本文的内容,您可以更好地利用Redis的特性,为应用程序提供高效的缓存和消息处理能力。
754 79

热门文章

最新文章

下一篇
oss云网关配置