简介及测试
Spring支持通过注解的方式来配置bean实例。Spring能够从classpath下自动扫描,侦测和实例化具有特定注解的组件。特定组件包括:
@Component:基本注解,标识了一个受Spring管理的组件。
@Repository:标识持久层组件。
@Service:标识服务车(业务层)组件。
@Controller:标识表现层组件。
现在模拟一下基本的MVC的调用关系,首先分别创建dao层,service层和controller层的组件:
public interface UserDao {
public void save();
}
@Repository("userDao")
public class UserDaoImpl implements UserDao {
@Override
public void save() {
System.out.println("UserDao save...");
}
}
@Service
public class UserService {
@Autowired
private UserDao userDao;
public void save(){
System.out.println("UserService save...");
userDao.save();
}
}
@Controller
public class UserAction {
@Autowired
private UserService userService;
public void save(){
System.out.println("UserAction save...");
userService.save();
}
}
对于扫描到的组件,Spring有默认的命名策略:使用非限定类名第一个字母小写的形式命名。也可以在注解中通过value属性值标识组件的名称,其中value是默认属性,可以直接以字符串的形式为注解的value属性赋值,例如在上述代码中,我们通过@Repository(“userDao”)的形式将UserDaoImpl实例命名为userDao。
当在组件类上使用了特点的注解之后,还需要在Spring的配置文件中声明<context:component-scan>:(在这里,我的所有要被扫描的组件类都在包com.MySpring.annotation下)
beans-annotation.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" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!-- 声明需要扫描的包 -->
<!-- 其中base-package属性指定需要扫描的基类包,spring容器将会扫描这个基类包及其子包中的所有类 -->
<!-- 当需要扫描多个包时,可以使用逗号分隔 -->
<context:component-scan base-package="com.MySpring.annotation"></context:component-scan>
</beans>
另外,<context:component-scan>元素还会自动注册AutowireAnnotationBeanPostProcessor实例,该实例可以自动装配具有@Autowired,@Resource,@Inject注解的属性。(通常都使用@Autowired)
编写测试类:
public class Test {
@org.junit.Test
public void test() {
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-annotation.xml");
UserAction userAction = (UserAction) ctx.getBean("userAction");
userAction.save();
}
}
如果报错如下:
java.lang.NoClassDefFoundError:org/springframework/aop/TargetSource
添加对应spring版本的aop jar包即可,例如我添加的是spring-aop-4.0.0.RELEASE.jar。然后即可成功运行:
关于<context:component-scan>节点
(1). 属性resource-pattern可以指定扫描基包下特定的类,而非所有类,例如:
<context:component-scan
base-package="com.MySpring.annotation"
resource-pattern="autowire/*.java"></context:component-scan>
(2). <context:include-filter>和<context:exclude-filter>子节点分别指明基类包下要包含的目标类和不包含的目标类,其属性如下:(前两个比较常用)
关于@Autowired
@Autowired注解自动装配具有兼容类型的单个bean属性。
默认情况下,所有使用@Autowired注解的属性都需要设置,当Spring找不到匹配的bean装配属性时,会抛出异常。若某一属性允许不被设置,可以设置@Autowired注解的required属性为false。
默认情况下,当IOC容器里存在多个类型兼容的bean时(例如现在UserDao接口有两个实现类,UserDaoImpl只是其一),通过类型的自动装配将无法工作。有两种解决方式,一种是像上述例子中一样,通过@Repository(“userDao”)设置UserDaoImpl实例的名称为userDao,然后在UserService中声明UserDao组件名为userDao即可。第二种方式是在装配属性上使用@Qualifier注解进行设置,例如在UserService中做如下设置:
@Autowired
@Qualifier("userDaoImpl")
private UserDao userDao;
就会加载UserDaoImpl这个实现类的实例。