2018暑期充实日记(3)Spring-DI

Spring 通过IOC,控制反转实现依赖注入。

依赖注入的三种方式:

(1)构造方法注入:即被注入对象可以通过在其构造方法中声明依赖对象的参数列表,让外部(通常是IOC容器)知道它需要哪些依赖对象,然后IOC容器会检查被注入对象的构造方法, 
取得其所需要的依赖对象列表,进而为其注入相应对象。

(2)setter方法注入:即当前对象只需要为其依赖对象所对应的属性添加setter方法,IOC容器通过此setter方法将相应的依赖对象设置到被注入对象的方式即setter方法注入。

还有一点需要注意:如果通过set方法注入属性,那么spring会通过默认的空参构造方法来实例化对象,所以如果在类中写了一个带有参数的构造方法,一定要把空参数的构造方法写上,否则spring没有办法实例化对象,导致报错。 

(3)接口注入:接口注入有点复杂,被注入对象如果想要IOC容器为其注入依赖对象,就必须实现某个接口,这个接口提供一个方法,用来为被注入对象注入依赖对象,IOC容器通过接口方法将依赖对象注入到被注入对象中去。相对于前两种注入方式,接口注入比繁琐和死板,被注入对象就必须专声明和实现另外的接口。

常用的是setter方法注入。通过注解或者XML都是可以的,具体方法网上很多不再赘述了。

xml配置

<bean id="priceorder" class="com.hjj.source.math.PriceOrder">
        <property name="money" value="1000"/>
        <property name="payway" ref="WeChat"/>
    </bean>
注解配置在下面的代码中可以直接看到,在PriceOrder类中。

这个依赖注入到底解决了什么问题呢?假如我们现在进行订单支付。

那么实际上具体业务实现的时候,开发者不需要知道用户是通过网银还是支付宝还是微信支付,这些是另外一个人的工作。只需要知道是否支付成功。(同时,这三者支付的方式在实现上肯定是不相同的,需要调用不同的API来实现)。

但是这个支付的方法是确定的,实现是不确定的情况下。不牵扯到具体属性的时候尽量多使用接口而非抽象类继承。

抽象类:强调的是把共同(共有、相同)的属性方法, 抽象出来,统一写在一个地方(他们的实现代码是一样的),方便维护。(面向对象三大特性中的继承特性

接口: 抽象的是行为 - 同一种行为的不同实现方式。当多个对象都拥有相同的行为,但是行为的具体实现方式不一样的时候可以用接口抽象(面向对象中的多态特性

善用接口和继承一直是一个设计上很难的问题,我的理解也只是初步的。可能是有误的,但是现在这种理解能帮助我的编程开发。

声名pay接口
public interface pay {
    public boolean paymoney(int money);
}

实现了WeChat和Zfb两个支付方式,implements了pay接口

@Repository(value = "WeChat")
public class WeChat implements pay{
    public boolean paymoney(int money) {
        //这里调用WeChat的支付接口
        System.out.println("通过WeChat支付成功,支付金额为:"+money);
        return true;
    }
}
@Repository(value = "Zfb")
public class ZFB implements pay{
    public boolean paymoney(int money) {
        //这里调用ZFB的支付接口进行支付
        System.out.println("通过ZFB支付成功,支付金额为:"+money);
        return true;
    }
}

Service订单类

@Service("priceorder")
public class PriceOrder {
    private int money = 1000;
    @Resource(name = "WeChat")
    private pay payway;
    public void setMoney(int money) {
        this.money = money;
    }
    public int getMoney() {
        return money;
    }
    public pay getPayway() {
        return payway;
    }
    public void setPayway(pay payway) {
        this.payway = payway;
    }
    public void pay(){
        if (payway.paymoney(money)) money -= 1000;
    }
    public void rest(){
        System.out.println("剩余余额为:"+money);
    }
}

Test测试

public class Test {

    public static void main(String[] args) throws InterruptedException {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("aop.xml");
        math1 math = (math1) ctx.getBean("math");
        PriceOrder priceOrder = (PriceOrder)ctx.getBean("priceorder");
        priceOrder.pay();
        priceOrder.rest();
    }

}

可以看到我这里在声名priceOrder的时候,没用new一个新的pay对象,对象由spring自动生成并注入(见前面@Resource)。我对注入的对象不需要了解,只需要对业务进行开发。

现在只是一个对象,当需要创建的对象复杂且繁多,并且很多都是别的package里的对象的时候,程序员很难了解每个对象创建需要依赖的对象,需要不断查找创建赋值,这个行为是很浪费时间并且极易出错的,因此DI(依赖注入)给予了程序员开发上的极大方便。

这里我又用了一下AOP结合着来做

@Before(value = "execution(* com.hjj.source.math.WeChat.paymoney(..))")
    public void before(JoinPoint point){
        Date date = new Date();
        System.out.println(date+"一笔新的支付订单");
        System.out.println("@Before:模拟权限检查...");
        System.out.println("@Before:目标方法为:" +
                point.getSignature().getDeclaringTypeName() +
                "." + point.getSignature().getName());
        System.out.println("@Before:参数为:" + Arrays.toString(point.getArgs()));
        System.out.println("@Before:被织入的目标对象为:" + point.getTarget());
//        获取方法名

    }

在每次支付之前,输出时间和一些日志消息。

Thu Jun 21 10:25:48 CST 2018一笔新的支付订单
@Before:模拟权限检查...
@Before:目标方法为:com.hjj.source.math.WeChat.paymoney
@Before:参数为:[1000]
@Before:被织入的目标对象为:com.hjj.source.math.WeChat@3e96bacf
通过WeChat支付成功,支付金额为:1000
剩余余额为:0

总结一下,DI依赖注入避免了程序员去寻找类的依赖对象,也避免了多次创建依赖对像引起的混乱问题,使得程序员对编码之外的情况不需要进行关心,提高了开发效率。

AOP则是在不影响业务的情况下,为整个程序添加系统级别的功能,特别是日志记录,非常好用和方便,对框架的侵入性低。



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值