注解装配分三步走
1.先标识这是可装配的组件(扫描)
- 组件扫描:(component scanning):
Spring能够从classpath下自动扫描,侦测,实例化具有特定注解的组件。 - 特定的组件包括:
@Component: 基本注解, 标识了一个受 Spring 管理的组件
@Respository: 标识持久层组件
@Service: 标识服务层(业务层)组件
@Controller: 标识表现层组件
对于扫描到的组件,Spring具有默认的命名策略:使用非限定性类名,第一个首字母小写;
也可在注解中通过value属性标识值标识组件的名称。
2.在XML文件中进行装配。
- 当在组件中使用了特定的注解以后,还要在Spring的配置文件中声明<context: component-scan>
- base-package属性指定一个需要扫描的基类包,Spring会扫描包及其子包的所有类。
- <context:include-filter>子节点包含的目标类
- <context:exclude-filter>子节点排除的目标类
<context:include-filter>、 <context:exclude-filter>支持多种类型的过滤表达式
常用的:annotation(根据注解) assignable(根据类或接口)
如何建立bean与bean之间的引用关系?
<context: component-scan>会自动注册AutowiredAnnotationBeanPostProcessor实例,该实例可以自动装配@Autowired 、@Resource、@inject注解的属性。
3.Bean之间引用关系的装配
@Autowired与@Resource都可以用来装配bean. 都可以写在字段上,或写在setter方法上。
@Autowired默认按类型装配(这个注解是属于spring的),默认情况下必须要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,如:@Autowired(required=false) 。如果我们想使用名称装配可以结合@Qualifier注解进行使用,如下:
使用@Autowired注释进行byType注入,如果需要byName(byName就是通过id去标识)注入,增加@Qualifier注释。
@Qualifier
一般在候选Bean数目不为1时应该加@Qualifier注释。
在默认情况下使用 @Autowired 注释进行自动注入时,Spring 容器中匹配的候选 Bean 数目必须有且仅有一个。当找不到一个匹配的 Bean 时,Spring 容器将抛BeanCreationException 异常,并指出必须至少拥有一个匹配的 Bean。
和找不到一个类型匹配 Bean 相反的一个错误是:如果 Spring 容器中拥有多个候选 Bean,Spring 容器在启动时也会抛出 BeanCreationException 异常。
表现层:
public class UserController {
@Autowired
private Userservice userservice;
public void execute(){
System.out.println("user controlling");
userservice.add();
}
}
业务层:
public class Userservice {
private UserRepository userRepository;
@Autowired
@Qualifier("userRepositoryJDBC")
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
public void add()
{
System.out.println("UserService add...");
userRepository.save();
}
}
持久层:
public interface UserRepository {
void save();
}
@Repository
public class UserRepositoryImpl implements UserRepository {
@Override
public void save() {
System.out.println("userepository saving。。。");
}
}
@Repository
public class UserRepositoryJDBC implements UserRepository {
@Override
public void save() {
System.out.println("jdbc saving...");
}
}
TestObject:
@Component
public class TestObject {
}
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.xsd">
<!--指定容器要扫描的包 -->
<!--通过resource-pattern指定扫描的资源 -->
<!--
<context:component-scan
base-package="com.spring.annotation"
resource-pattern="repository/*.class">
</context:component-scan>
-->
<!--include-filter要配合use-default-filters="false" 使用-->
<!--
<context:component-scan
base-package="com.spring.annotation" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"></context:include-filter>
</context:component-scan>
-->
<!--
<context:component-scan
base-package="com.spring.annotation" use-default-filters="false">
<context:include-filter type="assignable" expression=" com.spring.annotation.repository.UserRepository"></context:include-filter>
</context:component-scan>
-->
<context:component-scan
base-package="com.spring.annotation" > </context:component-scan>
</beans>
泛型依赖注入
在父类建立依赖关系,子类只要继承了它们,就能够建立相应的依赖关系。
BaseRepository
public class BaseRepository<T> {
}
BaseService
public class BaseService<T> {
//在父类中建立依赖关系
@Autowired
protected BaseRepository<T> repository;
public void add(){
System.out.println("adding...");
System.out.println(repository);
}
}
User
public class User {
}
UserRepository
@Repository
public class UserRepository extends BaseRepository<User> {
}
UserService
@Service
public class UserService extends BaseService<User> {
}
注入的泛型类型要匹配,并都要继承父类,子类之间才会自动继承父类的依赖关系,调用父类的方法时才会用具体的子类类型替代
Main
public class Main {
public static void main(String[] args) {
ClassPathXmlApplicationContext actxt = new ClassPathXmlApplicationContext("beans-generic.xml");
UserService us = (UserService) actxt.getBean("userService");
us.add();
}
}
打印:
信息: Loading XML bean definitions from class path resource [beans-generic.xml]
adding...
com.spring.generic.UserRepository@15bfd87