注解的基本概念
Java1.5引入了注解,当前许多java框架中大量使用注解,如Hibernate、Jersey、Spring。注解作为程序的元数据嵌入到程序当中。注解可以被一些解析工具或者是编译工具进行解析。我们也可以声明注解在编译过程或执行时产生作用。
在使用注解之前,程序源数据只是通过java注释和javadoc,但是注解提供的功能要远远超过这些。注解不仅包含了元数据,它还可以作用于程序运行过程中、注解解释器可以通过注解决定程序的执行顺序。例如,在Jersey webservice 我们为方法添加URI字符串的形式的**PATH**注解,那么在程序运行过程中jerser解释程序将决定该方法去调用所给的URI。
几种常见注解的介绍
1.@Controller:用于标注控制层,注入服务
2.@RestController:@RestController注解相当于@ResponseBody + @Controller合在一起的作用,也是用于标注控制层。
其中,@Controller和@RestController区别如下:
1) 如果只是使用@RestController注解Controller,则Controller中的方法无法返回jsp页面,或者html,配置的视图解析器 InternalResourceViewResolver不起作用,返回的内容就是Return 里的内容。
2) 如果需要返回到指定页面,则需要用 @Controller配合视图解析器InternalResourceViewResolver才行。
如果需要返回JSON,XML或自定义mediaType内容到页面,则需要在对应的方法上加上@ResponseBody注解。
例如:使用@Controller 注解,在对应的方法上,视图解析器可以解析return 的jsp,html页面,并且跳转到相应页面
若返回json等内容到页面,则需要加@ResponseBody注解
@CrossOrigin @Controller public class FileUploadController { //跳转到上传文件的页面 @RequestMapping(value="/gouploadimg", method = RequestMethod.GET) public String goUploadImg() { //跳转到 templates 目录下的 uploadimg.html return "uploadimg"; } //处理文件上传 @RequestMapping(value="/testuploadimg", method = RequestMethod.POST) public @ResponseBody String uploadImg(@RequestParam("file") MultipartFile file, HttpServletRequest request) { System.out.println("调用文件上传方法"); String contentType = file.getContentType(); String fileName = file.getOriginalFilename();
而由于@RestController注解相当于@Controller+@ResponseBody两个注解的结合,因此返回json数据不需要在方法前面加@ResponseBody注解了,但使用@RestController这个注解,就不能返回jsp,html页面,视图解析器无法解析jsp,html页面
@CrossOrigin @RestController /* @Controller + @ResponseBody*/ public class HospitalController { //注入Service服务对象 @Autowired private HospitalService hospitalService; /** * 查询所有医院信息(未分页) */ @RequestMapping(value = "findAllHospital",method = RequestMethod.GET) public List<Hospital> findAllHospital(){ List<Hospital> hospitalList= hospitalService.findAllHospital(); return hospitalList; }
@repository:用于标注数据访问层,也可以说用于标注数据访问组件,即DAO组件.(实现dao访问)
@Service:标注服务层,注入dao,主要用来进行业务的逻辑处理
@Component:泛指各种组件,就是说当我们的类不属于各种归类的时候(不属于@Controller、@Services等的时候),我们就可以使用@Component来标注这个类,(把普通pojo实例化到spring容器中,相当于配置文件中的 <bean id="" class=""/>
)
@Qualifier:当创建多个具有相同类型的 bean 时,并且想要用一个属性只为它们其中的一个进行装配,在这种情况下,你可以使用 @Qualifier 注释和 @Autowired 注释通过指定哪一个真正的 bean 将会被装配来消除混乱。
下面显示的是使用 @Qualifier 注释的一个示例。
先说明下场景,代码如下:
有如下接口:
public interface EmployeeService { public EmployeeDto getEmployeeById(Long id); }
同时有下述两个实现类 EmployeeServiceImpl和EmployeeServiceImpl1:
@Service("service") public class EmployeeServiceImpl implements EmployeeService { public EmployeeDto getEmployeeById(Long id) { return new EmployeeDto(); } } @Service("service1") public class EmployeeServiceImpl1 implements EmployeeService { public EmployeeDto getEmployeeById(Long id) { return new EmployeeDto(); } }
调用代码如下:
@Controller @RequestMapping("/emplayee.do") public class EmployeeInfoControl { @Autowired EmployeeService employeeService; @RequestMapping(params = "method=showEmplayeeInfo") public void showEmplayeeInfo(HttpServletRequest request, HttpServletResponse response, EmployeeDto dto) { #略 } }
在启动tomcat时报如下错误:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'employeeInfoControl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.test.service.EmployeeService com.test.controller.EmployeeInfoControl.employeeService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.test.service.EmployeeService] is defined: expected single matching bean but found 2: [service1, service2]
其实报错信息已经说得很明确了,在autoware时,由于有两个类实现了EmployeeService接口,所以Spring不知道应该绑定哪个实现类,所以抛出了如上错误。
这个时候就要用到@Qualifier注解了,qualifier的意思是合格者,通过这个标示,表明了哪个实现类才是我们所需要的,我们修改调用代码,添加@Qualifier注解,需要注意的是@Qualifier的参数名称必须为我们之前定义@Service注解的名称之一!
@Controller @RequestMapping("/emplayee.do") public class EmployeeInfoControl { @Autowired @Qualifier("service") EmployeeService employeeService; @RequestMapping(params = "method=showEmplayeeInfo") public void showEmplayeeInfo(HttpServletRequest request, HttpServletResponse response, EmployeeDto dto) { #略 } }
@Autowired :默认按类型装配(这个注解是属业spring的),默认情况下必须要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,如:@Autowired(required=false),如果我们想使用按名称装配,可以结合@Qualifier注解一起使用。如下:
@Autowired() @Qualifier("baseDao") private BaseDao baseDao;
@Resource:是JDK1.6支持的注解,默认按照名称进行装配,名称可以通过name属性进行指定,如果没有指定name属性,当注解写在字段上时,默认取字段名,按照名称查找,如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。只不过注解处理器我们使用的是Spring提供的,是一样的,无所谓解耦不解耦的说法,两个在便利程度上是等同的。
byName 通过参数名 自动装配,如果一个bean的name 和另外一个bean的 property 相同,就自动装配。
byType 通过参数的数据类型自动自动装配,如果一个bean的数据类型和另外一个bean的property属性的数据类型兼容,就自动装配
@Scope:用于指定scope作用域的(用在类上)
下面写这个是引入component的扫描组件 ,用注解来向Spring容器注册Bean
<context:component-scan base-package=”com.mmnc”>
表明com.mmnc包及其子包中,如果某个类的头上带有特定的注解【@Component/@Repository/@Service/@Controller】,就会将这个对象作为Bean注册进Spring容器。也可以在<context:component-scan base-package=” ”/>中指定多个包,如:
1 <context:component-scan base-package="package_1,package_2"/>
多个包逗号隔开。
其中base-package为需要扫描的包(含所有子包)
1、@Service用于标注业务层组件
2、@Controller用于标注控制层组件(如struts中的action)
3、@Repository用于标注数据访问组件,即DAO组件.
4、@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
参考网址
https://www.cnblogs.com/clwydjgs/p/9255083.html
https://www.cnblogs.com/smileLuckBoy/p/5801678.html
https://blog.csdn.net/ws379374000/article/details/78528572
https://www.zhihu.com/question/39356740
https://www.cnblogs.com/xdp-gacl/p/3495887.html