Spring 自动扫描与自动装配(Autowiring)

今天学习 Spring 框架中的自动扫描组件与自动装配相关知识点。

Spring有几种属性来设置具体的装配


  1. No ---- 不做任何操作,通过 ref attribute手动设定。
  2. byname ---- 根据属性名(Property Name)自动装配。此选项将检查容器并根据名字查找与属性完全一致的另一个bean,并将其与属性自动装配
  3. byType ---- 如果容器中存在一个与指定属性类型相同的bean,那么将与该属性自动装配;如果存在多个该类型的bean,那么抛出异常,并指出不能使用byType方式进行自动装配;如果没有找到相匹配的bean,则什么事都不发生
  4. Constructor ---- 与byType方式类似,不同之处在于它应用于构造器参数。如果容器中没有找到与构造器参数类型一致的bean,那么抛出异常
  5. autodetect ---- 如果发现默认的构造函数,用 constructor 模式,否则,用 byType 模式。

Bean的自动装配:在beans标签配置属性 default-autowire="no/byName/byType/constructor"

作用:省去了在Spring的xml中配置property标签和constructor-arg标签,只需要配置bean标签即可

PS:byName和byType为设值注入,constructor为构造注入;byName要求bean标签的id属性需要和成员变量的名称一致,byType和constructor则跟id无关


通常可以在 xml 配置文件中,声明一个 bean 或者 component ,然后 Spring 容器会检查和注册你的 bean 或 component 。实际上Spring 支持自动扫描 bean 或 component ,不必再在 xml 文件中繁琐的声明 bean ,Spring 会自动扫描、检查你指定包的 bean 或 component 。


写个简单的手动配置的Spring Project ,使用maven来创建,包含Customer,Service,DAO层,以上不做具体业务实现,只是进行声明测试.

创建maven项目

修改pom.xml,添加Spring依赖

    <dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.3.4.RELEASE</version>
    </dependency>
</dependencies>

CustomerDAO类

package net.boy.spring.SpringAuto;

public class CustomerDAO {
    
    @Override
    public String toString() {
        return "This is CustomerDAO ";
    }
    

}

CustomerService类

package net.boy.spring.Services;

import net.boy.spring.SpringAuto.CustomerDAO;

public class CustomerService {
    
    CustomerDAO customerDAO;
    
    public void setCustomerDAO(CustomerDAO customerDAO) {
        this.customerDAO = customerDAO;
    }
    
    @Override
    public String toString() {
        return "CustomerService : customerDAO = " + customerDAO;
    }

}

在main下创建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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd">
           
            <bean id="customerService" class="net.boy.spring.Services.CustomerService">
                <property name="customerDAO" ref="customerDAO"></property>
            </bean>

           
           <bean id="customerDAO" class="net.boy.spring.SpringAuto.CustomerDAO">
           </bean>
  
  
  </beans>

创建App测试类

package net.boy.spring.SpringAuto;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import net.boy.spring.Services.CustomerService;

public class App{

    public static void main(String[] args) {
        ApplicationContext context = 
                new ClassPathXmlApplicationContext(new String[] {"springAuto.xml"});
        
        CustomerService service = (CustomerService) context.getBean("customerService");
        System.out.println(service);
    }
    

}

以上为手工配置方式,实现默认装配可配置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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd" 
        default-autowire="constructor">

    </beans>

通过default-autowire="constructor"属性设置装配模式,属性值分别是前面的几种方式,对于不同属性进行不同的注入方式,这种就省去了<property></property>的声明.Spring自动装


但是还有使用@Component注解来表示这个Class是一个自动扫描组件,而且Spring还是鼓励这种方式来实现,来减少配置文件的大小,增加程序的紧密性.

上面的Class使用@Component注解

配置xml文件

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
              http://www.springframework.org/schema/context
                http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/beans 
            http://www.springframework.org/schema/beans/spring-beans.xsd">

     <context:component-scan base-package="net.boy.spring" />

</beans>

context:component-scan 标签 ,Spring将自动扫描特性引入;base-package 表示组件的存放位置,Spring 将扫描对应文件夹下的 bean(用 @Component 注释过的),将这些 bean 注册到容器中。

默认情况下.Spring 将把组件 Class 的第一个字母变成小写,来作为自动扫描组件的名称.

如下

super.getBean("beanScope");

自定义扫描组件名称

@Service("boy")
public class BeanScope 

现在变成

super.getBean("boy");

自动扫描组件的注释类型

有 4 种注释类型,分别是:

@Component ——表示一个自动扫描 component

@Repository ——表示持久化层的 DAO component

@Service ——表示业务逻辑层的 Service component

@Controller ——表示表示层的 Controller compone

自动扫描中过滤组件

Filter Component - include

组件只要匹配定义的"regex"的命名规则,Class 前就不需要用 @Component 进行注释。

    <context:component-scan base-package="net.boy.spring" >

        <context:include-filter type="regex" 
                       expression="net.boy.spring.*Bean.*" />

    

    </context:component-scan>

Filter Component——exclude

制定组件避免被 Spring 发现并被注册到容器中。以下配置排除用 @Service 注释过的组件:

<context:component-scan base-package="net.boy.spring" >
        <context:exclude-filter type="annotation" 
            expression="org.springframework.stereotype.Service" />        
</context:component-scan>

使用JAVA正则

<context:component-scan base-package="com.lei" >
        <context:exclude-filter type="regex" 
            expression="net.boy.spring.dao.*DAO.*" />        
</context:component-scan>

使用自动装配大大提高开发效率,但是提高了配置文件的复杂性.先整理这么多,以后多多运用来加深理解..

最后由 不一样的少年 编辑于2016年12月10日 22:39