专栏首页Java识堂Spring中XML,注解,JavaConfig如何选择

Spring中XML,注解,JavaConfig如何选择

前言

Spring的IOC极大的方便了我们的编程,当我们需要某个对象的时候,不在需要自己去new,只要告诉Spring一声,Spring就会把我们所需要的类准备好,就像你原来出门要穿外套时,你得先跑到衣柜前取出衣服,然后自己穿上。现在好了,你结婚了,只要跟你的另一半说一声,她就会心领神会,把衣服给你拿过来,然后帮你穿上,是不是感觉很爽?Spring有三种配置方法,这三种配置方式如何选择?先看一下这三种配置方式

XML

applicationContext.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"
       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="knight" class="com.st.BraveKnight">
        <constructor-arg ref="weapon"/>
    </bean>

    <bean id="weapon" class="com.st.Weapon">
        <property name="type" value="knife"/>
    </bean>
</beans>
public class BraveKnight {

    private Weapon weapon;

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

    public Weapon getWeapon() {
        return weapon;
    }
}
public class Weapon {

    private String type;

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }
}
public class Main {

    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        BraveKnight knight = context.getBean(BraveKnight.class);
        // knife
        System.out.println(knight.getWeapon().getType());
        context.close();
    }
}

这样一个Spring项目就完成了,可以用spring的test模块,进行测试

@RunWith(SpringJUnit4ClassRunner.class)
// 多个文件时可用locations = {"", ""}
@ContextConfiguration(locations = "classpath*:/applicationContext.xml")
public class XMLTest {

    @Autowired
    BraveKnight braveKnight;

    @Test
    public void test() {
        // knife
        System.out.println(braveKnight.getWeapon().getType());
    }
}

用XML形式可以在配置文件中,配置我们自己写的类和外部库的类,Spring通过反射可以把这些类都创建出来,并由Spring管理,在你需要的时候给你

注解

@Component
public class BraveKnight {

    @Autowired
    private Weapon weapon;

    public Weapon getWeapon() {
        return weapon;
    }
}
@Component
public class Weapon {

    @Value("knife")
    // 这个值可以从外部配置文件中通过@Value注解读取到
    private String type;

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }
}
@Configuration
// 如果不配置扫描的路径,默认扫描配置类所在的包及其子包下面的所有类
@ComponentScan
public class MyConfig {
}
public class Main {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.register(MyConfig.class);
        context.refresh();
        BraveKnight knight = context.getBean(BraveKnight.class);
        // knife
        System.out.println(knight.getWeapon().getType());
        context.close();
    }
}
@RunWith(SpringJUnit4ClassRunner.class)
// 从类中读取配置
@ContextConfiguration(classes = MyConfig.class)
public class AnnotaionTest {

    @Autowired
    BraveKnight braveKnight;

    @Test
    public void test() {
        // knife
        System.out.println(braveKnight.getWeapon().getType());
    }
}

JavaConfig

在我们自己的类上,我们可以加@Component注解让Spring来管理,如果是第三方jar包的类呢?它的类上并不会加@Component啊,如果不想用XML来生成第三方jar包的类,JavaConfig在这个时候就派上用场了,接着上面的例子,假如Weapon这个类是第三方jar包的类,则可以通过如下形式让Spring管理

@Configuration
// 如果不配置扫描的路径,默认扫描配置类所在的包及其子包下面的所有类
// 可以通过属性basePackages = {""}指定扫描的包
@ComponentScan()
public class MyConfig {

    // name属性默认是方法名,自己可以指定
    @Bean(name = "weapon")
    public Weapon weapon() {
        Weapon weapon = new Weapon();
        weapon.setType("knife");
        return weapon;
    }
}
  1. XML配置修改后不用重新编译,可以用于经常切换实现类的对象
  2. 注解用起来非常地简洁,代码量十分少,因此是项目的第一选择
  3. 当需要注入代码不是自己维护的第三方jar包中的类时,或者需要更为灵活地注入,比如说需要调用某个接口,查询数据,然后把这个数据赋值给要注入的对象,那么这时候就需要用到Java Config

后记

说一个我在用Spring集成Storm遇到的一个有意思的问题,一般想让外部库的类让Spring管理的方法,只要用XML或者JavaConfig配置即可,我项目中有一个ClassA需要继承Storm中的一个ClassB,但是ClassB是一个抽象类,不能在XML中配置,也不能在JavaConfig中创建出来,直接在ClassA上加上@Component注解,并不能让Spring管理ClassA,因为ClassB Spring管理不到,Spring就不能管理ClassA,这样就会导致ClassC注入失败

@Component
public class ClassA extends ClassB {

    @Autowired
    ClassC classC;
}

可能会有人想,直接new出来不就行了,奈何ClassC是如下形式

@Component
public class ClassC{

    @Autowired
    ClassD classD;
}

直接new出来,ClassD就不会被Spring注入进去,怎么办?回头看在启动类,这个类也没有被Spring管理,是怎么取到对象的?是从context中通过getBean方法拿的,但是在其他的类中怎么获取到context,其实Spring提供了一系列Aware接口,只要实现这些接口,就能获取到要东西,我们只要实现ApplicationContextAware接口,就可以获取到context,为了方便我直接封装了一个工具类,通过

SpringHellper.get(ClassC.class)

即可获取Spring管理的ClassC,并能在ClassA中愉快的使用了

@Component
public class SpringHelper implements ApplicationContextAware {

    private static ApplicationContext context;

    public static ApplicationContext getApplicationContext() {
        return context;
    }

    public static <T> T getBean(Class<T> requiredType) {
        return context.getBean(requiredType);
    }

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        context = applicationContext;
    }
}

注意要加上Component注解,这样在Spring启动后这个类的context属性就被填充进来了

本文分享自微信公众号 - Java识堂(erlieStar)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-06-29

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 你知道 OOM 常见原因吗?有什么好的解决方法?

    当 JVM 内存严重不足时,就会抛出 java.lang.OutOfMemoryError 错误。本文总结了常见的 OOM 原因及其解决方法,如下图所示。如有遗...

    用户1516716
  • java 并发篇- 概念篇

    各位好,今天是我们并发篇正式开始的第一篇,既然我们大家学习并发,那么就要理解一些计算机概念最好,否则,知道怎么用而不知道名称是啥,概念含糊不清,以及不知道怎么设...

    haoming1100
  • 上车时机已到--.NETCore是适应时代发展的雄鹰利剑

    随着 .NET Core 3.0-prevew7 的发布,开源社区的一支重要力量重要即将起飞;官方指出,该预览版为可能为最终版本,在很长一段时间内,.NETCo...

    梁规晓
  • 听说优秀的程序员20%的时间都在写UT?

    在今天的文章中打算和大家聊一聊关于测试的话题,也许有朋友会问,作为一名码农为什么要关注测试的问题?我们把代码开发完基本自测没问题了,扔给测试不就行了?有问题再改...

    用户5927304
  • Java 并发篇-04.synchronized

    大家好,缓缓来迟的第 5 篇 并发内容,其实准备了好久了,因为想写点不一样的内容,结果导致托了一个月才准备好。在开始正文之前,继续来我们的几个灵魂问题:

    haoming1100
  • 如何测试概率型业务接口

    在我做接口测试的工作中,有段时间负责产品的每星期活动的接口测试,需求一般比较简单,但是有一批活动很特殊,在之前的工作中都没遇到过,就是概率型业务。常见的抽奖、随...

    八音弦
  • 如何动手撸一个简单的LFU缓存

    关于第一种FIFO策略的实现,比较简单,可采用固定长度的数组和链表来处理,这里就不重点说了。今天我们的重点是LFU缓存的实现。

    我是攻城师
  • Java 并发篇03 -序性、可见性、原子性。

    这篇文章,我们将给大家来讲解引起我们并发问题的三大因素--— 有序性、可见性、原子性。这三个问题是属于并发领域的所以并不涉及语言。

    haoming1100
  • 【趣学程序】Java中的异常

    趣学程序
  • 为什么项目中用了JOOQ后大家都不愿再用Mybatis?

    今天给大家介绍一个新的ORM框架->JOOQ,可能很多朋友还没有听说过这个框架,码农哥之前也是一直在使用Mybatis框架作为Java工程中的持久层访问框架,但...

    用户5927304

扫码关注云+社区

领取腾讯云代金券