Spring中的Bean配置
在说bean配置之前需要先说下Spring中重要功能之一IOC容器:
一 IOC容器
IOC(Inversion of Control) :即反转控制,思想是反转资源获取的方向,传统方式是组件向容器发起请求查找资源. 作为回应, 容器适时的返回资源。而应用了 IOC 之后, 则是容器主动地将资源推送给它所管理的组件, 组件所要做的仅是选择一种合适的方式来接收资源. 这种行为也被称为查找的被动形式。
DI(Dependency Injection):即依赖注入,IOC 的另一种表述方式:即组件以一些预先定义好的方式(例如: setter 方法)接受来如容器的资源注入. 相对于 IOC 而言,这种表述更直接。
举个例子,之前如果想使用某个对象的方法,需要先获取对象的实例,new个对象实例,再调用其方法。而使用IOC之后,我们无需创建对象,因为容器已经帮我们创建好了,我们只需要调用该方法即可,IOC容器会将资源主动推送给我们。
//传统方式
@Test
public void test1() {
HelloWorld helloWorld =new HelloWorld();
helloWorld.setUserName("world");
helloWorld.Hello();
}
//IOC容器
@Test
public void test2() {
ApplicationContext con = new ClassPathXmlApplicationContext("applicationContext.xml");
HelloWorld helloWorld =(HelloWorld) con.getBean("helloWorld");
helloWorld.Hello();
}
二 配置bean
1、基于 XML 文件的方式
<!-- 配置一个 bean -->
<bean id="helloWorld1" class="com.atguigu.spring.helloworld.HelloWorld">
<!-- 为属性赋值 -->
<!-- 通过属性注入: 通过 setter 方法注入属性值,Bean必须有无参构造器, 实际应用中最常用的注入方式-->
<property name="user" value="Tom"></property>
</bean>
<!-- 通过构造器注入属性值 -->
<bean id="helloWorld2" class="com.atguigu.spring.helloworld.HelloWorld">
<!-- 要求: 在 Bean 中必须有对应的构造器,<constructor-arg> 中没有 name 属性 -->
<constructor-arg value="Mike"></constructor-arg>
</bean>
<!-- 若一个 bean 有多个构造器, 如何通过构造器来为 bean 的属性赋值 -->
<!-- 可以根据 index 和 value 进行更加精确的定位. -->
<bean id="car" class="com.atguigu.spring.helloworld.Car">
<constructor-arg value="KUGA" index="1"></constructor-arg>
<constructor-arg value="ChangAnFord" index="0"></constructor-arg>
<constructor-arg value="250000" type="float"></constructor-arg>
</bean>
2基于注解的方式
需要在配置文件中配置:context:component-scan 标签,自动扫描配置的包。配置后可以自动装配具有 @Autowired 和 @Resource 、@Inject注解的属性.最常用的是@Autowired
在配置文件中配置自动扫描的包
<!-- 配置自动扫描的包: 需要加入 aop 对应的 jar 包,否则报错NoClassDefFoundError -->
<context:component-scan base-package="com.java.spring.*"></context:component-scan>
在组件中加入如下注解:
@Component: 基本注解, 标识了一个受 Spring 管理的组件
@Respository: 标识持久层组件
@Service: 标识服务层(业务层)组件
@Controller: 标识表现层组件
如果仅希望扫描特定的类而非基包下的所有类,可使用 resource-pattern 属性过滤特定的类,例如我只想扫描*Action的类:
<context:component-scan base-package="com.java.spring.*" resource-pattern="*Action.class">
</context:component-scan>
此外context:component-scan下还有两个子节点:
context:include-filter :表示要包含的目标类
context:exclude-filter :表示要排除在外的目标类
context:include-filter 和 context:exclude-filter 子节点支持多种类型的过滤表达式:
annotation | 注解类,该类型采用目标类是否包含了某个注解进行过滤 |
---|---|
assignable | 是否继承或扩展了某类,该类型采用目标类是否继承或扩展某个特定的类进行过滤 |
aspectj | 所有类名以某某结束及 继承或扩展某个特定的类进行过滤 |
regex | 采用正则表达式对类名进行过滤 |
custom | 通过代码的方式定义过滤 |
最常用的是前两种,后三种不常用。
第一种举例:
<!-- 不扫描含有Controller注解的类 -->
<context:component-scan base-package="com.java.spring.*">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!-- 扫描含有Servicer注解的类 ,还需要配置use-default-filters="false"-->
<context:component-scan base-package="com.java.spring*" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
</context:component-scan>
第二种举例:
<context:component-scan base-package="com.java.spring*" use-default-filters="false">
<!-- 包含BaseDao以及继承了它的子类 -->
<context:include-filter type="assignable" expression="com.java.spring.service.UsreService"/>
<!-- 不包含BaseDao以及继承了它的子类 -->
<context:exclude-filter type="assignable" expression="com.java.spring.generic.BaseDao"/>
</context:component-scan>
context:component-scan> 下可以拥有若干个 context:include-filter 和 context:exclude-filter 子节点,但是顺序有要求,include节点在前,exclude在后。执行顺序从前到后,顺序执行。举个例子,如果配置的类一样,比如说include要求包含Controller注解而exclude又要求不包含Controller注解,实际上是不会包含的
<context:component-scan base-package="com.java.spring*" use-default-filters="false">
<!-- 扫描包含Controller注解的类 -->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<!-- 扫描不包含Controller注解的类 -->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>