Spring注解
2021/5/7 周五
学习内容:@Autowired,@Qualifier,@Resource,@AliasFor,@Component,@Controller,@Scope,@Service,@Repository等。
如有错误,欢迎在评论区指出,非常感谢!
一、为什么要用注解
传统的Spring做法是使用.xml文件来对bean进行注入或者是配置aop、事物,这么做有两个缺点:
- 如果所有的内容都配置在.xml文件中,那么.xml文件将会十分庞大;如果按需求分开.xml文件,那么.xml文件又会非常多。总之这将导致配置文件的可读性与可维护性变得很低。
- 在开发中在.java文件和.xml文件之间不断切换,是一件麻烦的事,同时这种思维上的不连贯也会降低开发的效率。
为了解决这两个问题,Spring引入了注解,通过"@XXX"的方式,让注解与Java Bean紧密结合,既大大减少了配置文件的体积,又增加了Java Bean的可读性与内聚性。
二、Spring注解的使用
使用前必须告诉spring一下我要使用注解了,告诉的方式有很多,<context:component-scan base-package=“xxx” /> 是一种最简单的,spring会自动扫描xxx路径下的注解。
Spring中的注解大概可以分为两大类:
-
spring的bean容器相关的注解,或者说bean工厂相关的注解:
@Autowired,@Required,@PostConstruct, @Qualifier, @AliasFor等; -
springmvc相关的注解:
@Controller,@Service,@RequestMapping,@ResponseBody等。
三、常用的Bean容器相关注解
1. @Autowired
@Autowired顾名思义,就是自动装配,其作用是为了消除代码Java代码里面的getter/setter与bean属性中的property。
@Autowired默认按类型匹配的方式,当Spring发现@Autowired注解时,将自动在代码上下文中找到和其匹配的Bean,当有且仅有一个匹配的Bean时,Spring将其注入@Autowired标注的变量中。
@Autowired 是我们使用得最多的注解,其实就是 autowire=byType ,就是根据类型的自动注入依赖(基于注解的依赖注入),可以被使用在属性域,方法,构造函数上。
2. @Qualifier(指定注入Bean的名称)
@Qualifier 就是 autowire=byName, @Qualifier 通常和@Autowired一起使用,一般在两个或者多个bean是相同的类型时,spring注入会出现混乱,就需要使用 @Qualifier(“xxBean”) 来指定Bean的名称。
- 例如
定义一个Car接口,两个实现类BMWCar和BenzCar:
再写一个CarFactory,引用car(这里先不用@Qualifier注解):
Car接口有两个实现类,Spring并不知道应当引用哪个实现类。
通常有两种解决办法:
(1) 在配置文件中删除其中一个实现类,Spring会自动去base-package下寻找Car接口的实现类,发现Car接口只有一个实现类,便会直接引用这个实现类。
(2) 实现类就是有多个该怎么办?此时可以使用@Qualifier注解来指定Bean的名称:
@Autowired
@Qualifier("bmwCar")
private ICar car;
此处会注入名为"bmwCar"的Bean。
3. @Resource
@Resource(name="tiger")
private Tiger tiger;
@Resource(type=Monkey.class)
private Monkey monkey;
@Resource的装配顺序:
(1) @Resource后面没有任何内容,默认通过name属性去匹配bean,找不到再按type去匹配
(2) 指定了name或者type则根据指定的类型去匹配bean
(3) 指定了name和type则根据指定的name和type去匹配bean,任何一个不匹配都将报错
@Resource 与 @Autowired 的区别:
(1) @Autowired默认按照byType方式进行bean匹配,@Resource默认按照byName方式进行bean匹配
(2) @Autowired是Spring的注解,@Resource是J2EE的注解,这个看一下导入注解的时候这两个注解的包名就一清二楚了
Spring属于第三方的,J2EE是Java自己的东西,因此,建议使用@Resource注解,以减少代码和Spring之间的耦合。
4. @AliasFor
(1)组合注解:
@AliasFor可以把多个元注解的属性组合在一起形成新的注解,从而到达到便捷的目的。这样的注解我们可以称之为复合注解。
如@SpringBootApplication组合了@Configuration、@ComponentSan、@EnnableAutoConfiguration,所以在使用SpringBoot 时我们只需要@SpringBootApplication一个注解就能开启。
(2) 属性别名
在同个注解中为同一个功能定义两个名称不一样的属性,那么这两个属性彼此互为别名,这是为了能做到顾名思义,使之达到一目了然的效果,我们可以根据需要选择一个更加贴合特定场景的名称。
5. @Component
@Component是所有受Spring 管理组件的通用形式,@Component注解可以放在类的头上,@Component不推荐使用。
四、SpringMVC相关注解
1. @Controller
对应Controller层控制层的Bean。
使用@Controller注解标识UserController之后,就表示要把UserController交给Spring容器管理,在Spring容器中会存在一个名字为"userController"的controller。
(这个名字是根据UserController类名来取的,如果@Controller不指定其value,即直接【@Controller】,则默认的bean名字为这个类的类名首字母小写;如果指定value,即【@Controller(value=“UserController”)】或者【@Controller(“UserController”)】,则使用指定的value作为bean的名字。)
2. @Scope
使用@Controller时还经常会使用 @Scope 注解。
Spring 默认scope 是单例模式(scope=“singleton”),这样只会创建一个Controller对象,每次访问都是同一Controller对象,数据不安全,例如struts2 要求每次次访问都对应不同的Controller,这时就需要用@scope注解了。
【@Scope(“prototype”)】表示将Controller的范围声明为原型(scope=“prototype”),即可以利用容器的 scope="prototype"来保证每一个请求都创建一个单独的Controller来处理,避免struts中Controller的线程安全问题。
3. @Service
对应的是Service层服务层的Bean。
@Service
public class UserServiceImpl implements IUserService
......
}
使用@Service标注UserServiceImpl后,当Controller需要使用UserServiceImpl的实例时,就可以由Spring创建好"userService",然后注入给Controller,在Controller只需要声明一个名字叫"userService"的变量来接收由Spring注入的"userService"即可。
// Controller里注入userService
@Resource(name = "userService")
private UserService userService;
同样可以直接用【@Service】,或者用【@Service(“UserService”)】告诉Spring创建UserServiceImpl的实例时,bean的名字必须叫做"UserService"。
注意,在Controller声明的"userService"变量的类型必须是"UserServiceImpl"或者是其父类"UserService",否则由于类型不一致而无法注入。
4. @Repository
@Repository对应数据访问层的Bean ,例如:
@Repository(value="userDao")
public class UserDaoImpl extends BaseDaoImpl<User> {
......
}
【@Repository(value=“userDao”)】注解是告诉Spring,让Spring创建一个名字叫"userDao"的UserDaoImpl实例。
当Service需要使用Spring创建的名字叫"userDao"的UserDaoImpl实例时,就可以使用【@Resource(name = “userDao”)】注解告诉Spring,Spring把创建好的userDao注入给Service即可。
// 注入userDao,从数据库中根据用户Id取出指定用户时需要用到
@Resource(name = "userDao")
private BaseDao<User> userDao;
主要参考文章:
1.https://www.cnblogs.com/szlbm/p/5512931.html
2.https://www.cnblogs.com/estellez/p/4570015.html