五 Spring常用注解,自动扫描装配Bean

 

spring自动扫描机制

spring2.5为我们引入了组件自动扫描机制,它可以在classPath路径底下寻找标注了@Component、@Service、@Controller、@Repository注解的类,并把这些类纳入进spring容器中管理。它的作用和在xml文件中使用bean节点配置组件是一样的。

也就是要spring自动扫描机制只会查找指定类路径下包含@Component、@Service、@Controller、@Repository这四种注解的类。

要使用自动扫描机制,我们需要打开以下配置信息:

1、引入context命名空间 需要在xml配置文件中配置以下信息: 同上先引入context 命名空间,同时

2、在配置文件中添加context:component-scan标签

<context:component-scan base-package="*"/> 

其中base-package为需要扫描的包(含子包)。

注:

1、在使用组件扫描元素时,AutowiredAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessor会隐式地被包括进来。 也就是说,连个组件都会被自动检测并织入 - 所有这一切都不需要在XML中提供任何bean配置元数据。也就是说如果使用了context:component-scan标签,就可以不需要再引入context:annotation-config标签

<context:component-scan />还允许定义过滤器将基包下的某些类纳入或排除。Spring支持以下4种类型的过滤方式:
过滤器类型 表达式范例 说明 
注解 org.example.SomeAnnotation 将所有使用SomeAnnotation注解的类过滤出来 
类名指定 org.example.SomeClass 过滤指定的类 
正则表达式 com\.kedacom\.spring\.annotation\.web\..* 通过正则表达式过滤一些类 
AspectJ表达式 org.example..*Service+ 通过AspectJ表达式过滤一些类 

以正则表达式为例,我列举一个应用实例:

Java代码 
<context:component-scan base-package="com.casheen.spring.annotation"> 
    <context:exclude-filter type="regex" expression="com\.casheen\.spring\.annotation\.web\..*" />
</context:component-scan> 

        <context:component-scan base-package="com.casheen.spring.annotation">
                <context:exclude-filter type="regex" expression="com\.casheen\.spring\.annotation\.web\..*" />
        </context:component-scan>

值得注意的是<context:component-scan />配置项不但启用了对类包进行扫描以实施注释驱动Bean定义的功能,同时还启用了注释驱动自动注入的功能(即还隐式地在内部注册了AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor),因此当使用<context:component-scan />后,就可以将<context:annotation-config />移除了。


六   常用注解

 

--定义Bean的注解

 

@Controller

@Controller("Bean的名称")

定义控制层Bean,如Action

 

@Service          

@Service("Bean的名称")

定义业务层Bean

 

@Repository   

@Repository("Bean的名称")

定义DAO层Bean

 

@Component  

定义Bean, 不好归类时使用.

 

--自动装配Bean (选用一种注解就可以)

@Autowired  (Srping提供的)

默认按类型匹配,自动装配(Srping提供的),可以写在成员属性上,或写在setter方法上

 

@Autowired(required=true)  

一定要找到匹配的Bean,否则抛异常。 默认值就是true 

 

@Autowired

@Qualifier("bean的名字") 

按名称装配Bean,与@Autowired组合使用,解决按类型匹配找到多个Bean问题。

 

@Resource   JSR-250提供的

默认按名称装配,当找不到名称匹配的bean再按类型装配.

可以写在成员属性上,或写在setter方法上

可以通过@Resource(name="beanName") 指定被注入的bean的名称, 要是未指定name属性, 默认使用成员属性的变量名,一般不用写name属性.

@Resource(name="beanName")指定了name属性,按名称注入但没找到bean, 就不会再按类型装配了.

 

@Inject   是JSR-330提供的

按类型装配,功能比@Autowired少,没有使用的必要。

 

--定义Bean的作用域和生命过程

@Scope("prototype")

值有:singleton,prototype,session,request,session,globalSession

 

@PostConstruct 

相当于init-method,使用在方法上,当Bean初始化时执行。

 

@PreDestroy 

相当于destory-method,使用在方法上,当Bean销毁时执行。

 

--声明式事务

@Transactional

六   配置工厂Bean 

         通常由应用程序直接使用new创建新对象,为了将对象的创建与使用相分离,采用工厂模式,即应用程序将对象的创建与初始化交给工厂来完成。        一般情况下,应用程序有自己的工厂对象来创建bean,如果将工厂对象交给Springle管理,那么Spring管理的就不是普通的bean,而是工厂Bean。调用getBean()方法,Spring返回的不是直接创建的Bean的实例,而是由工厂创建的Bean实例。



一般在Spring中配置工廠Bean,有3中不同類型的工廠Bean的配置. 


1.静态工厂 創建具體Bean實例的是靜態方法 


[java] view plain copy

  1. import java.util.Random;   
  2. public class Static FactoryBean{   
  3. public static  
  4. Integer createRandom() {   
  5. return new  
  6. Integer(new Random().nextInt());  
  7. }  
  8. }   

    將其納入Spring容器來管理,需要通過factory-method指定静态方法名称,方法必须是static的,才能找到。

[java] view plain copy

[java] view plain copy

  1. <bean id="random"  
  2. class="example.chapter3.StaticFactoryBean"  
  3. factory-method="createRandom"//createRandom方法必須是static的,才能找到  
  4. scope="prototype"  
  5. />   



測試: 

[java] view plain copy

  1. public static void main(String[] args) {  
  2. XmlBeanFactory factory = new XmlBeanFactory(new  
  3. ClassPathResource("config.xml"));  
  4. System.out.println(factory.getBean("random").toString());   
  5. //StaticFactoryBean sfb =  
  6. (StaticFactoryBean)factory.getBean("random");  
  7. //System.out.println(sfb.createRandom().toString());   
  8.   
  9. //調用getBean()時,返回隨機數.如果沒有指定factory-method,會返回StaticFactoryBean的實例,即返回工廠Bean的實例  
  10. }   

2.实例工厂  創建具體Bean實例的是實例,不是靜態方法 

[java] view plain copy

  1. import java.text.SimpleDateFormat;  
  2. import java.util.Date;   
  3. public class InstanceFactoryBean {   
  4. private String format = "yy-MM-dd HH:mm:ss";   
  5. public void setFormat(String format) {  
  6. this.format = format;  
  7. } public String createTime() {  
  8. return new SimpleDateFormat(format).format(new Date());  
  9. }  
  10. }  



 配置文件需要配置兩個bean:第一個Bean和普通的Bean沒有區別,第二個bean定義如何通過工廠Bean獲取Bean,需要指定工廠Bean的名稱和方法名稱  

[java] view plain copy

  1. <bean id="instanceFactoryBean" class="example.chapter3.InstanceFactoryBean">  
  2. "format" value="yyyy-MM-dd HH:mm:ss"/>  
  3. </bean>   
  4. <bean id="currentTime" factory-bean="instanceFactoryBean" factory-method="createTime"/>   

  測試: 

[java] view plain copy

  1. public static void main(String[] args) {  
  2. XmlBeanFactory factory = new XmlBeanFactory(new  
  3. ClassPathResource("config.xml"));  
  4. System.out.println(factory.getBean("currentTime"));  
  5. }   

3.實現FactoryBean接口 

[java] view plain copy

  1. public class PiFactoryBean implements FactoryBean {   
  2. public Object getObject() throws Exception {  
  3. return new Double(3.14159265358979);  
  4. } public Class getObjectType() {  
  5. return Double.class;  
  6. } public boolean isSingleton() {  
  7. return true;  
  8. } }   

實現了FactoryBean接口的Bean,不再被視爲普通的Bean.Spring會自動檢測. 


[java] view plain copy

  1. <bean id="pi"class="example.chapter3.PiFactoryBean"/>  

   測試 

[java] view plain copy

  1. public static void main(String[] args) throws Exception {  
  2. XmlBeanFactory factory = new XmlBeanFactory(new  
  3. ClassPathResource("config.xml"));  
  4. System.out.println(factory.getBean("pi"));//返回PiFactoryBean  
  5. 的工廠方法getObject返回的Double對象實例  
  6. //PiFactoryBean p =  
  7. (PiFactoryBean)factory.getBean("&pi");  
  8. //加"&"返回工廠Bean的實例.  
  9. //System.out.println(p.getObject());  
  10. }