900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > 用IOC和DI解决懒人老板想喝咖啡但不想自己动手的窘迫

用IOC和DI解决懒人老板想喝咖啡但不想自己动手的窘迫

时间:2018-11-20 11:27:23

相关推荐

用IOC和DI解决懒人老板想喝咖啡但不想自己动手的窘迫

懒人公司里,所有人都非常的懒惰,唯独他们的程序员还在拼命的奋斗。这一天老板想喝咖啡。

public void boss(){System.out.println("我想喝咖啡");}

这时候老板走到了咖啡机。

public void cofo_jiqi(){System.out.println("我是咖啡机");}

但是老板现在并不会泡咖啡(别问我为什么不会,这是个蠢货懒老板)这时我教给他了泡咖啡的方法。

public void boss(){System.out.println("我想喝咖啡");//泡咖啡的方法Cofo cofo = new Cofo();cofo.cofo_jiqi();}

好啦,老板成功的泡好了一杯咖啡。但是没过多久,他又想喝咖啡了。由于这是懒人公司,所以老板也懒到极致,他叫了自己手下唯一勤奋的程序员:小王,去让他帮自己泡咖啡。

chengxuyuan Mr_wang = new chengxuyuan();

程序员小王叫过来了

小王被老板忽悠的团团转,屁颠屁颠的要帮老板泡咖啡。

chengxuyuan Mr_wang = new chengxuyuan();Mr_wang.pao_cofo();

可是小王的技能只有写代码,我们还要教会他泡咖啡才行。

class chengxuyuan{public void Write(){System.out.println("我会写代码");}public void pao_cofo(){System.out.println("我会泡咖啡");Cofo cofo = new Cofo();cofo.cofo_jiqi();}}

好了,现在我们教会小王泡咖啡了。这时候这个懒人老板的得力泡咖啡助手就是小王了。

讲了这么多,其实经过这个例子,我们就已经明白了iOC中控制反转的概念了。之前老板想泡咖啡,必须自己来。

老板需要知道,这个咖啡机是怎么用的,但是老板怎么会连这种低级的东西都学呢!!!所以这时候我们就需要用一个工具人。

这时候老板只需要张张嘴,让小王这个工具人来做,自己不需要动,也不需要知道咖啡机怎么用,都让小王来帮你,你需要做的就是躺在座椅上,饭来张口。我们做老板可能都喜欢这种潇洒的生活,程序也不例外。

1.控制反转

光听名字,大家应该就可以听出个一二,控制反转嘛,不就是本来属于自己控制的事情,反过来让其他人帮你控制。其实话粗理不粗,控制反转的意思大可这样理解。即通过控制传递给我代码,但实际上我并没有直接依赖于它们。这并非我的代码调用了什么更通用的代码,而是框架允许我插入自定义的行为。像这样系统设计使用的就是所谓的控制反转(简称IOC)。

当然肯定有人会想,这和我平常new对象有什么区别什么好处呢。当然我上面说的例子中,这些好处肯定不足以什么,那我就仔细讲讲他的好处。

通过解耦改善模块化

在我们的实际开发过程中,都是一块大肉多人分,一个项目多人做,这样的就是模块化。要是我们平常用new来获取对象,就大大增加了代码的耦合。让两个类变的互不可缺,这个是很不应该的。假如后期的项目,各类开始分层,挪动,到时候要是还是用new的话,必定会出现很多错误。这样的话,程序员不可能一个个找错误,那太麻烦了。所以这时候我们的IOC容器就会帮我们自动找类,来给你注入这个对象。

不用考虑创建对象的过程,只需要找IOC容器拿对象

我们可以把我们的小王当做一个ioc容器。我们只需要考虑的是,喝什么咖啡,而不用考虑这个咖啡是怎么泡出来的。大大的节省了代码量和逻辑。

那我们该如何创建一个IOC容器,让他帮我们管理对象呢。我们用Spring来做这个例子。

配置bean

就是将我们的对象信息,放入bean里面

<bean id = "chengxuyuan" class="com.sun.been.chengxuyuan"></bean><bean id ="cofo" class="com.sun.been.Cofo"></bean>

ID放的是我们的对象名字,类似A a = new A();里的 a。

class就是这个类的地址。

那么这两个对象有了,我们想想,还需要写什么吗??对了,我们既然要让小王帮我们泡咖啡,那我们必须要学会怎么跑咖啡啊,这时候我们给他写个泡咖啡的方法。

<bean id = "chengxuyuan" class="com.sun.been.chengxuyuan"><property name="cofo" ref="cofo"></property></bean><bean id ="cofo" class="com.sun.been.Cofo"></bean>

好了,那我们来看看,代码该如何获取到这些配置的呢。

首先我们要从IOC容器中获得程序员小王这个对象。

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");chengxuyuan Mr_wang = applicationContext.getBean("chengxuyuan",chengxuyuan.class);

这个是个固定用法,意思是获得一个容器对象ApplicationContext,让他读取bean.xml里的配置。接下来,我们用容器的对象,将程序员小王给获取出来,之所以要用chengxuyuan.class,是因为传过去的应该是个字节码对象。需要进行类型转换。当然也可以在前面写个强转,两者都可实现。

这时候小王叫来了,要让小王泡咖啡了,但是小王这时候还是不会的,我们需要教他,这时候我们就需要用DI来注入这个方法。

public void setCofo(Cofo cofo) {this.cofo = cofo;}private Cofo cofo;

这时,你肯定就有疑惑了,这样写不会空指针异常吗,因为我们没有给对象给到cofo啊。no!no!no!这里我们的IOC容器就已经从bean.xml,找到了这个对象,并且让这个对象,等于bean.xml里我们已经配置好了的 ,cofo这个对象。所以这就是IOC容器一个强大之处,di注入。(这里是个固定用法,想让Ioc帮你注入,就只能这样写)这时候我们来运行一下

这个咖啡就已经泡好了。

那大家有没有发现,一直用bean.xml来配置对象信息,是不是太麻烦了。要是有一百个对象,那对于以后的运维都是一个困难,那我们有没有一个好的方法来简化xml呢。答案是有的,Spring专门为我们准备了注解,来完成bean.xml里的操作。我们需要使用以下几个注解:

@Autowired顾名思义,就是自动装配,其作用是为了消除代码Java代码里面的getter/setter与bean属性中的property。当然,getter看个人需求,如果私有属性需要对外提供的话,应当予以保留。

@Autowired默认按类型匹配的方式,在容器查找匹配的Bean,当有且仅有一个匹配的Bean时,Spring将其注入@Autowired标注的变量中。

用法就是写在你的方法的上面。

// public void setCofo(Cofo cofo) {// this.cofo = cofo;// }@Autowiredprivate Cofo cofo;

这个注解在XML中将

<property name="cofo" ref="cofo"/>

替代了。

省去了set方法,可以直接匹配方法。但是要注意,要是这个bean,有多个,再或者是没有,都会报错,因为是按类型匹配这个对象。那一旦出现了这种情况该怎么办呢?

@Resource注解与@Autowired注解作用非常相似

这是详细一些的用法,说一下@Resource的装配顺序:

(1)、@Resource后面没有任何内容,默认通过name属性去匹配bean,找不到再按type去匹配

(2)、指定了name或者type则根据指定的类型去匹配bean

(3)、指定了name和type则根据指定的name和type去匹配bean,任何一个不匹配都将报错

然后,区分一下@Autowired和@Resource两个注解的区别:

(1)、@Autowired默认按照byType方式进行bean匹配,@Resource默认按照byName方式进行bean匹配

(2)、@Autowired是Spring的注解,@Resource是J2EE的注解,这个看一下导入注解的时候这两个注解的包名就一清二楚了

Spring属于第三方的,J2EE是Java自己的东西,因此,建议使用@Resource注解,以减少代码和Spring之间的耦合。

@Service

@Repository

@Component

这三个的用法是一样的,只不过是由于分层,才会出现三个注解,其底层代码都是一样的。将这个类放入IOC容器中,替代了xml中

<bean id = "chengxuyuan" class="com.sun.been.chengxuyuan"></bean><bean id ="cofo" class="com.sun.been.Cofo"></bean>

的操作。但是这样创建的bean都是单例模式,假如我们的实际开发中要用到多例模式,配置@Scope即可,默认是"singleton"即单例,"prototype"表示原型即每次都会new一个新的出来。

但是要注意通过注解来配置ioc容器,我们的bean.xml是需要添加一行标签,以此来扫描我们的注解。

<context:component-scan base-package="com.sun"></context:component-scan>

里面的参数package就是填写需要扫描注解的包。

那么现在 我们的整体代码就已经变成这样了

package com.sun.been;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import org.ponent;/*** SpringIoc和DI例子*/public class test {/*** 测试类入口*/public static void main(String[] args) {/*** 扫描配置文件,获取对象*/ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");chengxuyuan Mr_wang = applicationContext.getBean("chengxuyuan",chengxuyuan.class);System.out.println("我想喝咖啡");Mr_wang.pao_cofo();}}/*** 程序员类*/@Componentclass chengxuyuan{@Autowired()private Cofo cofo;public void Write(){System.out.println("我会写代码");}public void pao_cofo(){System.out.println("我会泡咖啡");cofo.cofo_jiqi();}}/*** 咖啡类*/@Componentclass Cofo{public void cofo_jiqi(){System.out.println("我是咖啡机");}}

bean.xml也只剩

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:context="/schema/context"xsi:schemaLocation="/schema/beans/schema/beans/spring-beans.xsd/schema/context/schema/context/spring-context-4.0.xsd"><context:component-scan base-package="com.sun"></context:component-scan></beans>

总结

使用注解之前要开启自动扫描功能,其中base-package为需要扫描的包(含子包)。

<context:component-scan base-package=“cn.test”/>

@Configuration把一个类作为一个IoC容器,它的某个方法头上如果注册了@Bean,就会作为这个Spring容器中的Bean。

@Scope注解 作用域

@Lazy(true) 表示延迟初始化

@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。

@Repository用于标注数据访问组件,即DAO组件。

@Service用于标注业务层组件、

@Controller用于标注控制层组件(如struts中的action)

@Scope用于指定scope作用域的(用在类上)

@Autowired 默认按类型装配,如果我们想使用按名称装配,可以结合@Qualifier注解一起使用。如下:

@Autowired @Qualifier(“personDaoBean”) 存在多个实例配合使用

@Resource默认按名称装配,当找不到与名称匹配的bean才会按类型装配。

@PostConstruct用于指定初始化方法(用在方法上)

@PreDestory用于指定销毁方法(用在方法上)

@DependsOn:定义Bean初始化及销毁时的顺序

@Primary:自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否则将抛出异常

@PostConstruct 初始化注解

@PreDestroy 摧毁注解 默认 单例 启动就加载

@Async异步方法调用

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。