一、Spring 在classpath下自动扫描组件
•Spring 能够从classpath下自动扫描,侦测和实例化具有特定注解的组件.
•特定组件包括:
–@Component: 基本注解,标识了一个受Spring管理的组件
–@Respository:标识持久层组件
–@Service: 标识服务层(业务层)组件
–@Controller: 标识表现层组件
•对于扫描到的组件,
Spring
有默认的命名策略:使用非限定类名,第一个字母小写
.
也可以
在注解中通过
value
属性值标识组件的名称
•当在组件类上使用了特定的注解之后,还需要在Spring的配置文件中声明
<
context:component-scan
> :
–
base-package
属性指定一个需要扫描的基类包,
Spring
容器将会扫描这个基类包里及其子包中的所有类
.
–
当需要扫描多个包时
,
可以使用逗号分隔.
如果仅希望扫描特定的类而非基包下的所有类,可使用resource-pattern属性过滤特定的类
–
<
context:include-filter
>
子节点表示要包含的目标类
–
<
context:exclude-filter
>
子节点表示
要排除在外的
目标
类
–<context:component-scan>下可以拥有若干个<context:include-filter>和<context:exclude-filter>子节点
•<context:include-filter>和<context:exclude-filter>子节点支持多种类型的过滤表达式
示例:
1.com.spring.beans.annotation.controller包下的 UserController类
package com.spring.beans.annotation.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import com.spring.beans.annotation.service.UserService;
@Controller
public class UserController {
//Spring 将 自动装配 名为 userService 的bean
@Autowired
private UserService userService123;
public void exec() {
System.out.println("UserController exec...");
userService123.add();
}
}
2.com.spring.beans.annotation.service包下的UserService类
package com.spring.beans.annotation.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import com.spring.beans.annotation.repository.UserRepository;
@Service
public class UserService {
@Autowired(required=false) //IOC容器中没有该类型实例时,可以不装配
@Qualifier("userRepository") //有多个该类型的bean时,指定装配哪一个
private UserRepository userRepository;
//@Autowired 也可注解在set方法上
//@Qualifier("userRepository") 也可写在入参的前边
// public void setUserRepository(UserRepository userRepository) {
// this.userRepository = userRepository;
// }
//@Autowired
//@Qualifier("userRepository")也可不写在方法上,写在入参的前边
// public void setUserRepository(@Qualifier("userRepository")UserRepository userRepository) {
// this.userRepository = userRepository;
// }
public void add(){
System.out.println("UserSevice add...");
userRepository.save();
}
}
3.com.spring.beans.annotation.repository 包下的接口UserRepository及两个实现类
UserRepository接口
package com.spring.beans.annotation.repository;
public interface UserRepository {
void save();
}
实现类UserRepositoryImpl
package com.spring.beans.annotation.repository;
import org.springframework.stereotype.Repository;
// 通过value属性标识组件名称
// 因为value是默认属性,所以value="userRepository" 可省略value=
@Repository("userRepository")
public class UserRepositoryImpl implements UserRepository{
@Override
public void save() {
System.out.println("UserRepository save...");
}
}
实现类UserJdbcRepository
package com.spring.beans.annotation.repository;
import org.springframework.stereotype.Repository;
@Repository
public class UserJdbcRepository implements UserRepository{
@Override
public void save() {
System.out.println("userJdbcRepository save ...");
}
}
4.com.spring.beans.annotation包下的示例实体类
package com.spring.beans.annotation;
import org.springframework.stereotype.Component;
@Component
public class TestObj {
}
配置文件
1.指定Spring IOC容器扫描的包
<!-- 指定Spring IOC容器扫描的包 -->
<context:component-scan
base-package="com.spring.beans.annotation">
</context:component-scan>
Spring将扫描到com.spring.beans.annotation包,及其子包下所有带特定注解的类,即TestObj,UserJdbcRepository,UserRepositoryImpl,UserService,UserController
当需要扫描多个包时,可以用逗号分隔
<!-- 指定Spring IOC容器扫描的包 -->
<!-- 可以通过 resource-pattern 指定扫描的资源 -->
<context:component-scan
base-package="com.spring.beans.annotation"
resource-pattern="repository/*.class">
</context:component-scan>
Spring将扫描到com.spring.beans.annotation包下, repository下所有带特定注解的类,即UserJdbcRepository,UserRepositoryImpl
3.使用context:exclude-filter 子节点指定排除哪些表达式的组件(排除特定注解的类)
<!-- context:exclude-filter 子节点指定排除哪些表达式的组件 -->
<context:component-scan
base-package="com.spring.beans.annotation">
<!-- 指定排除扫描 @Repository 注解-->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
</context:component-scan>
Spring将扫描com.spring.beans.annotation包下所有带特定注解的类,但不扫描带@Repository注解的类,即TestObj,UserService,UserController
4.使用context:include-filter 子节点指定包含哪些表达式组件(扫描特定的注解),该子节点需要use-default-filters="false"配合使用
<!-- context:include-filter 子节点指定包含哪些表达式组件,该子节点需要use-default-filters="false"配合使用-->
<context:component-scan
base-package="com.spring.beans.annotation"
use-default-filters="false">
<!-- 指定扫描 @Repository 注解-->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
</context:component-scan>
Spring将只扫描com.spring.beans.annotation包下带@Repository注解的类,即UserJdbcRepository,UserRepositoryImpl
5.使用context:exclude-filter 子节点指定排除哪些表达式的组件(排除继承或扩展特定的类)
<!-- context:exclude-filter 子节点指定排除哪些表达式的组件 -->
<context:component-scan
base-package="com.spring.beans.annotation">
<!-- 指定排除扫描 UserRepository 接口的实现类-->
<context:exclude-filter type="assignable" expression="com.spring.beans.annotation.repository.UserRepository"/>
</context:component-scan>
Spring将扫描com.spring.beans.annotation包下所有带特定注解的类,但不扫描继承或扩展UserRepository类,即最终扫描到TestObj,UserService,UserController
6.使用context:include-filter 子节点指定包含哪些表达式组件(扫描继承或扩展特定的类)
<!-- context:include-filter 子节点指定包含哪些表达式组件,该子节点需要use-default-filters="false"配合使用-->
<context:component-scan
base-package="com.spring.beans.annotation"
use-default-filters="false">
<!-- 指定扫描 UserRepository 接口的实现类-->
<context:include-filter type="assignable" expression="com.spring.beans.annotation.repository.UserRepository"/>
</context:component-scan>
Spring将扫描com.spring.beans.annotation包下
继承或扩展UserRepository类,即UserJdbcRepository,UserRepositoryImpl
二、利用注解建立bean和bean之间的引用关系
1. •<context:component-scan>元素还会自动注册AutowiredAnnotationBeanPostProcessor实例,该实例可以自动装配具有
@
Autowired
和
@Resource
、
@Inject注解的属性.
•@Autowired注解自动装配
具有兼容类型的单个 Bean属性
–构造器,普通字段(即使是非 public),一切具有参数的方法都可以应用@Authwired注解
–默认情况下, 所有使用@Authwired注解的属性都需要被设置. 当Spring 找不到匹配的 Bean 装配属性时, 会抛出异常,
若某一属性允许不被设置
,
可以设置
@
Authwired
注解的
required
属性为
false
–默认情况下,当IOC容器里存在多个类型兼容的Bean时,通过类型的自动装配将无法工作.此时可以在
@Qualifier 注解里提供Bean的名称.
Spring
允许对方法的入参标注
@
Qualifiter
已指定注入
Bean
的名称
– @Authwired注解也可以应用在
数组类型的属性上,此时Spring将会把所有匹配的Bean进行自动装配.
–@Authwired注解也可以应用在
集合属性上,此时Spring读取该集合的类型信息,然后自动装配所有与之兼容的Bean.
–@Authwired注解用
在
java.util.Map上时,若该Map的键值为String,那么Spring将自动装配与之Map值类型兼容的Bean,此时Bean的名称作为键值
可参照上面的java代码进行理解
2. @Autowired和@Inject,@Resource区别:
•
@Resource
注解要求提供一个
Bean
名称的属性,若该属性为空,则自动采用标注处的变量或方法名作为
Bean
的名称
•@Inject 和 @Autowired注解一样也是按类型匹配注入的Bean,但没有 reqired 属性
•
建议使用
@
Autowired
注解