Spring 自动扫描与自动装配
Spring 自动扫描与自动装配(Autowiring)
今天学习 Spring 框架中的自动扫描组件与自动装配相关知识点。
Spring有几种属性来设置具体的装配
- No ---- 不做任何操作,通过
ref attribute
手动设定。 - byname ---- 根据属性名(Property Name)自动装配。此选项将检查容器并根据名字查找与属性完全一致的另一个bean,并将其与属性自动装配
- byType ---- 如果容器中存在一个与指定属性类型相同的bean,那么将与该属性自动装配;如果存在多个该类型的bean,那么抛出异常,并指出不能使用byType方式进行自动装配;如果没有找到相匹配的bean,则什么事都不发生
- Constructor ---- 与byType方式类似,不同之处在于它应用于构造器参数。如果容器中没有找到与构造器参数类型一致的bean,那么抛出异常
- 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>