spring-quick-start例子解析

@ComponentScan

spring-quick-start是SpringFrameWork的一个入门级的例子。通过这个例子,我们还是可以学到一些东西的。

下面这个网址是这个例子的地址:

https://projects.spring.io/spring-framework/


第一步:

这个例子里,首先要下载依赖的类包spring-context,我选择的是用Gradle构建项目,如果你使用的是Maven进行构建的新,可以使用例子中的Maven依赖。

dependencies {
    compile 'org.springframework:spring-context:4.3.2.RELEASE'
}
spring-context模块是建立在Beans模块基础上的,并且提供了一些其它功能,例如国际化,事件传递,资源加载,Cache,Validation。而且它还支持很多JavaEE的特性,例如:EJB,JMX,JNDI等。ApplicationContext接口,是这个模块的核心。后面我们就会看到,如果使用ApplicationContext,在启动时把一些类当做Bean加载到Spring框架中,并使用ApplicationContext把那些Bean再读出来,让我们使用。

这个模块依赖了其它Spring的模块或第三方模块,例如:spring-beans,spring-core,spring-apo,commons-logging等等。


第二步:

写3个类:

 MessageService.java:一个接口类,定义了一个接口

 MessagePrinter.java:使用接口的类。它并不是实现接口的类,而是使用接口类。

 Application.java:启动类,并调用了上面的MessagePrinter来打印东西。

具体代码如下:

hello/MessageService.java

package hello;

public interface MessageService {
    String getMessage();
}


hello/MessagePrinter.java

package hello;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class MessagePrinter {

    final private MessageService service;

    @Autowired
    public MessagePrinter(MessageService service) {
        this.service = service;
    }

    public void printMessage() {
        System.out.println(this.service.getMessage());
    }
}


hello/Application.java

package hello;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.*;

@Configuration
@ComponentScan
public class Application {

    @Bean
    MessageService mockMessageService() {
        return new MessageService() {
            public String getMessage() {
              return "Hello World!";
            }
        };
    }

  public static void main(String[] args) {
      ApplicationContext context = 
          new AnnotationConfigApplicationContext(Application.class);
      MessagePrinter printer = context.getBean(MessagePrinter.class);
      printer.printMessage();
  }
}

下面来讲解上面类中相关的知识点:

(由于MessageService接口没有什么特殊性,省略不讲)

关于MessagePrinter类,首先要看的是两个注解@Component和@Autowired。

@Component:这个注解用在类上面,功能是把使用这个注解的类,自动生成一个Bean,哪个地方需要这个类型,就把它注入进去。

@Autowired:这个注解的功能是,告诉Spring,这个使用这个注解的属性(或方法),是需要从Spring管理的Bean中取得和属性(或方法参数)相同类型的Bean,注入到使用@Autowired的属性(或方法的参数)中去。这个就是我们上面介绍@Component时,所说的“哪个地方需要这个类型”中的所需要的地方。

使用这两个注解,有两个目的:

1,MessagePrinter要变成一个Bean,由Spring进行管理,在需要它的时候使用它(例如注入到属性中,或实例化它)

2,它的构造函数中的参数类型,在Spring管理的Bean中,有相同类型的话,就把那个Bean注入到构造函数的参数中。


关于Application类,这个类要介绍的比较多。

@Bean:这个注释的功能是,把方法的返回值变成一个被Spring管理的Bean。它和@Component很像,不同点就是它是把方法返回值变成Bean,而@Component则是把类变成Bean。

@Configuration:使用@Configuration注解的类标明它是一个bean的原始定义。还有,@Configuration类允许通过调用在相同类中的其他的@Bean方法来定义内部Bean的依赖。也就是有一个类使用@Configuration,这个类中的有两个方法使用了@Bean,其中有一个方法中的属性还依赖了另一个@Bean方法的返回值。

完全的@Configuration VS 简化的 @Bean模式?
当@Bean方法被声明在那些没有使用@Configuration注解注解的类上面,他们就是表面使用了一个简化的模式。例如:在一个@Component中或者甚至在一个普通的POJO类中被声明bean方法将会被当成是简化的模式。和完全的@Configuration不同,简化的@Bean方法不能被简单声明内部bean的依赖。一般来讲一个@Bean方法不应该调用其他的@Bean 方法在以一个简化的模式中。只有在@Configuration 类中使用@Bean方法才可以被建议使用完全的模式。这样可以方法可以防止相同的@Bean方法被多次的调用,从而防止减少了很难追寻的潜在BUG。

例如:把Application类中的MessageService mockMessageService()方法的所有内容移动到一个叫“NoConfigBean”的类中,这个类没有@Configuration注解,只有@Bean注解,再启动Application类的话,就会报错(如下)。但如果加上@Configuration就没有问题。

No qualifying bean of type [hello.MessageService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}

你可以使用在任何Spring 的@Component中使用@Bean注解的方法,但是,他们大部分应用在@Configuration 的bean中。

@ComponentScan:可以指定 Spring 框架去扫描指定包及其子包下的存在注解的类。如果不指定默认为当前类所在的包,以及子包。扫描的注解类型为:@Component,@Service,@Controller,@Repository,@Configuration,@Bean。其实这几种注解(除了@Component)内容都是一样的,只不过是注解名字不一样,以一种约定表示被注解的类的目的,用哪个其实最后的结果都是一样的。

有一点需要注意,AnnotationConfigApplicationContext构造函数参数类,在这个类上没有@ComponentScan的话,就不会去扫描那个可以成Bean的注解。原来以为只要其中有一个类上,有这个注解,就会去扫描那些注解。


最后介绍下面的代码:

ApplicationContext context = new AnnotationConfigApplicationContext(Application.class);

MessagePrinter printer = context.getBean(MessagePrinter.class);

基于Java类定义Bean配置元数据需要通过AnnotationConfigApplicationContext加载配置类及初始化容器,类似于XML配置文件需要使用ClassPathXmlApplicationContext加载配置文件及初始化容器。使用new AnnotationConfigApplicationContext(Application.class)创建应用上下文,构造器参数为使用@Configuration注解的配置类,读取配置类进行实例化相应的Bean。

因为Application类中,有@ComponentScan注解,所以在加载Application的时候,会把其它带上面说的特定注解的类扫描出来,变成Bean管理。

如果没有@ComponentScan注解的话,如何把其它带那个带配置注解的类加载成Bean呢?

有几个方法:

1,在AnnotationConfigApplicationContext构造函数中,指定多个参数,把想要加载的类加载进来。

    AnnotationConfigApplicationContext ctx1 = new AnnotationConfigApplicationContext(ApplicationContextConfig.class, ApplicationContextConfig2.class);

2,使用register方法进行注册

    AnnotationConfigApplicationContext ctx2 = new AnnotationConfigApplicationContext();  
    ctx2.register(ApplicationContextConfig.class);  
    ctx2.register(ApplicationContextConfig2.class); 

3,像使用@ComponentScan一样,指定要扫描的包,但是用scan方法来指定。

    public void testComponentScan() {  
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();  
        ctx.scan("cn.javass.chapter12.confiuration");  
        ctx.refresh();  
    } 

4,在配置类中,用@Import把其它的配置类加载进来。

    @Import({ApplicationContextConfig.class})

5,如果是xml类型的配置文件,可以使用@ImportResource把xml文件加载进来。

    @ImportResource({"config1.xml", "config2.xml"})



初始化完容器后,就可以从容器中取得我们想使用的Bean了。就是上面的第二行代码:MessagePrinter printer = context.getBean(MessagePrinter.class);


到此为止,spring-quick-start的讲解基本上完事了,希望对初学者有帮助。

代码地址:(在官方的代码基础上,为了试验做了一些小的修改)

https://github.com/hotdust/spring-quick-start


参考:(参考内容不止下面这些链接,但有一些找不到了,就不列出来了)

http://www.cnblogs.com/zhangminghui/p/4365048.html

http://jinnianshilongnian.iteye.com/blog/1463704


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值