一、常用注解的介绍
在Spring中,尽管使用 XML 配置文件可以实现 Bean 的装配工作,但如果应用中 Bean 的数量较多,会导致 XML 配置文件过于臃肿,从而给维护和升级带来一定的困难。Java从JDK 5.0以后,提供了Annotation(注解)功能,Spring 也提供了对Annotation技术的全面支持。Spring中定义了一系列的 Annotation(注解),接下来介绍一下常用的注解。
1、用于创建对象的注解
用于创建对象的注解相当于在bean.xml中配置<bean id="" class=""></bean>
(1)@Component:用于将当前类对象存入spring容器中,value属性用于指定bean的id。当不写时,默认值是当前类名,且首字母小写。
(2)@Controller:通常作用在控制层(Controller层),用于将控制层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。
(3)@Service:通常作用在业务层(Service 层),用于将业务层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。
(4)@Repository:用于将数据访问层(DAO层)的类标识为 Spring 中的 Bean,其功能与 @Component 相同。
(5)关于context:component-scan的说明:
1)使用 context 命名空间的 component-scan 元素进行注解的扫描,其 base-package 属性用于通知 spring 所需要扫描的目录。如下:
<context:component-scan base-package="com.yht.example4"></context:component-scan>
2)如果同时需要扫描多个包,有两种实现方式:
假设现在要扫描controller、service和dao三个包:
方式一:多个包之间使用逗号隔开。
<context:component-scan base-package="com.yht.example4.controller,com.yht.example4.service,com.yht.example4.dao"></context:component-scan>
方式二:配置扫描多个包的相同父目录。
<context:component-scan base-package="com.yht.example4"></context:component-scan>
3)配置给定包下要扫描哪些包——只扫描controller包和service包:
<!--
use-default-filters:设置为false,不使用默认的过滤规则。
include-filter:设置哪些包要扫描
-->
<context:component-scan base-package="com.yht.example4" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
</context:component-scan>
4)配置给定包下不扫描哪些包——不扫描controller包
<!--
exclude-filter:设置哪些包不扫描
-->
<context:component-scan base-package="com.yht.example4" use-default-filters="false">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
(6)案例:模拟UserSerive调用UserDao——注解方式实现
1)在xml中配置注解扫描的包。
<context:component-scan base-package="com.yht.example4"></context:component-scan>
2)创建UserService和IUserDao以及它的实现类UserDaoImpl,并加入注解。
@Service
public class UserService {
@Autowired
private IUserDao userDao;
public void execute(){
System.out.println("service的execute()方法");
userDao.findUser();
}
}
public interface IUserDao {
void findUser();
}
@Repository
public class UserDaoImpl implements IUserDao {
@Override
public void findUser() {
System.out.println("UserImpl1 的findUser()");
}
}
3)进行测试。
@Test
public void testAnno(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean6.xml");
UserService userService = context.getBean("userService", UserService.class);
userService.execute();
}
执行结果如下:
2、用于注入值的注解
用于注入值的注解相当于在bean.xml中给bean对象注入值的操作,<property name="" value=""></property>或<property name="" ref=""></property>
(1)@Autowired:用于对 Bean 的属性变量、属性的 Set 方法及构造函数进行标注,配合对应的注解处理器完成 Bean 的自动配置工作。默认按照 Bean 的类型进行装配。如上示例。
(2)@Qualifier:与 @Autowired 注解配合使用,会将默认的按 Bean 类型装配修改为按 Bean 的实例名称装配,Bean 的实例名称由 @Qualifier 注解的参数指定。
在上述例子中,如果IUserDao的子类有多个,那么此时@Autowired就会无法判断选择哪个子类进行注入,所以就需要@Autowired和@Qualifier一起使用。
在添加两个dao的实现类,此时就会报错如下:
No qualifying bean of type 'com.yht.example4.dao.IUserDao' available: expected single matching bean but found 3: userDaoImpl,userImpl1,userImpl2。
为service中的userDao对象添加@Qualifier注解即可解决此问题。如下:
@Autowired
@Qualifier(value = "userImpl1")
private IUserDao userDao;
执行结果如下:
(3)@Resource:既可以按照属性注入,也可以按照类型注入,@Resource是Java提供的,而不是Spring提供的。使用如下:
@Resource(name = "userImpl2")
private IUserDao userDao;
执行结果如下:
(4)@Value:用于注入基本类型和String类型的数据。给userService添加一个基本属性:name,使用@Value注入值并输出。
@Value("User Service")
private String name;
结果如下:
3、用于改变作用范围的注解
@Scope:用于指定bean的作用范围,其属性值value指定范围的取值,常用取值:singleton、prototype。
4、用于生命周期相关的
(1)@PreDestory:用于指定销毁方法。
(2)@PostConstruct:用于指定初始化方法。
5、其他新注解
(1)@Configuration:被注解的类是一个配置类。
(2)@ComponentScan:通过注解指定spring在创建容器时要扫描的包。和basePackages的作用是一样的,都是用于指定创建容器时要扫描的包。相当于XML中的<context:component-scan base-package="com.day2"></context:component-scan>
(3)@Import:导入其他的配置类。
(4)@Bean:用于把当前方法的返回值作为bean对象存入spring的ioc容器中
二、纯注解开发案例——无配置文件
模拟三层架构:查找用户。
目录结构如下:
1、MySpringConfig类作为配置类,代替原来的xml文件。
//作为配置类,代替xml
@Configuration
@ComponentScan("com.yht.example5")
public class MySpringConfig {
}
2、控制层的UserController
@Controller
public class UserController {
@Autowired
private IUserService userService;
public void isExist(){
System.out.println("controller层:判断用户是否存在");
userService.findUser();
}
}
3、service层的IUserService以及实现类。
public interface IUserService {
void findUser();
}
@Service
public class UserServiceImpl implements IUserService {
@Autowired
private IUserDao userDao;
@Override
public void findUser() {
System.out.println("service层:查找用户");
userDao.query();
}
}
4、dao层的IUserdao以及实现类
public interface IUserDao {
void query();
}
@Repository
public class UserDaoImpl implements IUserDao {
@Override
public void query() {
System.out.println("dao层:数据库查询");
}
}
4、单元测试
@Test
public void test(){
ApplicationContext context = new AnnotationConfigApplicationContext(MySpringConfig.class);
UserController userController = context.getBean("userController", UserController.class);
userController.isExist();
}
结果如下: