spring容器管理下,bean组件管理需要注意的点

1.错误代码示范

@Component
public class TransferUtilBiz {


    /**
     * 内部户转账
     */
    @Autowired
    private InnerAccountTransBiz innerAccountTransBiz;

    /**
     * 卡转账
     */
    @Autowired
    private CardTransBiz cardTransBiz;

    /**
     * 商户转账
     */
    @Autowired
    private MerchantTransBiz merchantTransBiz;

    /**
     * 客户转账
     */
    @Autowired
    private CustomerTransBiz customerTransBiz;

    /**
     * 转入方
     */
    private AbstractCommonTransferBiz transferIn;

    /**
     * 转出方
     */
    private AbstractCommonTransferBiz transferOut;


    /**
     * 获取转账处理类
     * @param entityType    实体类型
     * @return  转账处理类
     */
    private AbstractCommonTransferBiz getTransfer(String entityType){

        switch (EntityTypeEnum.valueOf(entityType)){
            case OPERATOR_NO:
                return customerTransBiz;
            case MERCHANT_NO:
                return merchantTransBiz;
            case ACCOUNT_NO:
                return innerAccountTransBiz;
            case CARD_NO:
                return cardTransBiz;
            default:
                return null;
        }

    }
transferUtilBiz.setTransferOut(EntityTypeEnum.ACCOUNT_NO.getCode());

 transferUtilBiz.setTransferIn(createTransOrderBO.getTransInEntityType());

这段代码的逻辑是在转账时根据参数获取对应的转账处理类,比如商户转个人,transferIn就是merchantTransBiz,

transferOut设置customerTransBiz,然后封装各自的参数处理转账。因为spring默认是单例的,所以在多线程的环境下

成员变量transferIn,transferOut可能会被修改,于是造成逻辑上的错误。所以在这个场景下是不应该给TransferUtilBiz 加成员

变量。而是应该直接去取转账的处理类,这样做是正确的。

用一个简单的例子模拟上述场景

public class Singleton {

    private static Singleton singleton;

    private int count;

    private Singleton() {}

    public static Singleton getInstance() {
        if (singleton == null) {
            singleton = new Singleton();
        }
        return singleton;
    }

    public static void main(String[] args) {

        ExecutorService pool = Executors.newFixedThreadPool(20);

        for(int i = 0 ; i < 20 ; i++){
            pool.submit(new Add());
        }
        pool.shutdown();
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }
}

public class Add implements Runnable{

    @Override
    public void run() {
        Singleton.getInstance().setCount(Singleton.getInstance().getCount()+1);
        System.out.println("当前数字为:"+Singleton.getInstance().getCount());
    }
}

上面的Singleton 是单例模式的简单写法(但是这里不能保证绝对是同一个对象),他有一个成员变量count,在线程池中

去累加然后获取值,不能保证数字打印的是一致的,,因为每个线程执行的情况是不一致的。A线程已经取到值17输出,然后代码往下执行一直以它的值为17,但是B线程可能已经将它的值改为19,也就是实际值已经不是预期的了。这就是上面所说的spring是默认单例的,尽量不要使用成员变量。对于上面的情况可以这样解决,下面的方法就是有序的了。最后说一下spring容器

在Spring中,bean可以被定义为两种模式:prototype(多例)和singleton(单例)

singleton(单例):只有一个共享的实例存在,所有对这个bean的请求都会返回这个唯一的实例。

prototype(多例):对这个bean的每次请求都会创建一个新的bean实例,类似于new。

使用注解可以这么设置:

public class Singleton {

    private static Singleton singleton;

    private int count;

    private Singleton() {}

    public static Singleton getInstance() {
        if (singleton == null) {
            singleton = new Singleton();
        }
        return singleton;
    }

    public static void main(String[] args) {

        ExecutorService pool = Executors.newFixedThreadPool(20);

        for(int i = 0 ; i < 100 ; i++){
            pool.submit(new Add());
        }
        pool.shutdown();
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }

    public static synchronized void add(){
        Singleton s = Singleton.getInstance();
        s.setCount(s.getCount()+1);
        System.out.println("当前数字为:"+s.getCount());
    }
}

public class Add implements Runnable{

    @Override
    public void run() {
        Singleton.add();
    }
}

2.正确代码示范

@Component
public class TransferUtilBiz {


    /**
     * 内部户转账
     */
    @Autowired
    private InnerAccountTransBiz innerAccountTransBiz;

    /**
     * 卡转账
     */
    @Autowired
    private CardTransBiz cardTransBiz;

    /**
     * 商户转账
     */
    @Autowired
    private MerchantTransBiz merchantTransBiz;

    /**
     * 客户转账
     */
    @Autowired
    private CustomerTransBiz customerTransBiz;

    /**
     * 获取转账处理类
     * @param entityType    实体类型
     * @return  转账处理类
     */
    public AbstractCommonTransferBiz getTransfer(String entityType){

        switch (EntityTypeEnum.valueOf(entityType)){
            case OPERATOR_NO:
                return customerTransBiz;
            case MERCHANT_NO:
                return merchantTransBiz;
            case ACCOUNT_NO:
                return innerAccountTransBiz;
            case CARD_NO:
                return cardTransBiz;
            default:
                throw new TradeProductException(BizErrorCode.ENTITY_TYPE_IS_ILLEGAL.getCode(),
                                                BizErrorCode.ENTITY_TYPE_IS_ILLEGAL.getDesc());
        }
    }
 //卡作为出账方支付工具
        transferUtilBiz.getTransfer(createTransOrderBO.getTransOutEntityType()).setFundOutPayTool(createTransOrderBO);

        //卡通用转账入帐方支付工具
        transferUtilBiz.getTransfer(createTransOrderBO.getTransInEntityType()).setFundInPayTool(createTransOrderBO);

 

3.如何在测试时复现这种问题。

一般在测试环境是单线程环境,因此会忽略多线程的情况。现在有一些并发测试工具,可以模拟多线程环境。

https://download.csdn.net/download/u013822349/10265013

4.如何以多态处理复杂条件表达式

这块代码原逻辑看起来比较复杂

可以按照类似下面的方式将条件表达式分解

public abstract class Employee {

    private int _type;

    static final int ENGINEER = 0;

    static final int SALESMEN = 1;

    static final int MANAGER = 2;


    public abstract int getType();

    static Employee create(int type){

        switch (type){
            case ENGINEER:
                return new Engineer();
            case SALESMEN:
                return new Salesmen();
            case MANAGER:
                return new Manager();
            default:
                throw new IllegalArgumentException("Incorrect type code default");
        }

    }

    abstract void excute();
}
public class Engineer extends Employee{

    @Override
    public int getType(){
        return Employee.ENGINEER;
    }

    @Override
    void excute() {
        System.out.println("ENGINEER");
    }
}

public class Manager extends Employee{

    @Override
    public int getType(){
        return Employee.MANAGER;
    }

    @Override
    void excute() {
        System.out.println("MANAGER");
    }

}

public class Salesmen extends Employee{

    @Override
    public int getType(){
        return Employee.SALESMEN;
    }

    @Override
    void excute() {
        System.out.println("SALESMEN");
    }

}

public class Main {

    public static void main(String[] args) {
        Employee.create(Employee.SALESMEN).excute();
    }
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值