Spring注解@Component、@Repository、@Service、@Controller区别
所以,如果 Web 应用程序采用了经典的三层分层结构的话,最好在持久层、业务层和控制层分别采用 @Repository、@Service 和 @Controller 对分层中的类进行注释,而用 @Component 对那些比较中立的类进行注释。
在一个稍大的项目中,通常会有上百个组件,如果这些组件采用xml的bean定义来配置,显然会增加配置文件的体积,查找以及维护起来也不太方便。 Spring2.5为我们引入了组件自动扫描机制,他可以在类路径底下寻找标注了@Component,@Service,@Controller,@Repository注解的类,并把这些类纳入进spring容器中管理。它的作用和在xml文件中使用bean节点配置组件时一样的。要使用自动扫描机制,我们需要打开以下配置信息:
Java代码
-
<?xml version="1.0" encoding="UTF-8" ?>
-
<beansxmlns="http://www.springframework.org/schema/beans"
-
xmlns:xsi="http://www.w3.org/2001/XMLSchemainstance"xmlns:context="http://www.springframework.org/schema/context"
-
xsi:schemaLocation="http://www.springframework.org/schema/beans
-
http://www.springframework.org/schema/beans/spring-beans2.5.xsd
-
http://www.springframework.org/schema/context
-
http://www.springframework.org/schema/context/spring-context-2.5.xsd" >
-
-
<context:component-scan base-package=”com.eric.spring”>
-
</beans>
6. 其中base-package为需要扫描的包(含所有子包) @Service用于标注业务层组件,@Controller用于标注控制层组件(如struts中的action),@Repository用于标注数据访问组件,即DAO组件,而@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
-
@Service
-
public class VentorServiceImpl implements iVentorService{
-
}
-
-
Repository
-
public class VentorDaoImpl implements iVentorDao {
-
}
- getBean的默认名称是类名(头字母小写),如果想自定义,可以@Service(“aaaaa”)这样来指定,这种bean默认是单例的,
- 如果想改变,可以使用
- @Service(“beanName”)
- @Scope(“prototype”)来改变。可以使用以下方式指定初始化方法和销毁方法(方法名任意):
-
@PostConstruct
-
public void init() {
-
}
-
-
@PreDestroy
-
public void destory() {
-
}
注入方式:
把DAO实现类注入到service实现类中,把service的接口(注意不要是service的实现类)注入到action中,注
入时不要new 这个注入的类,因为spring会自动注入,如果手动再new的话会出现错误,然后属性加上
@Autowired后不需要getter()和setter()方法,Spring也会自动注入。至于更具体的内容,等对注入的方式更
加熟练后会做个完整的例子上来。
注解:
在 spring的配置文件里面只需要加上<context:annotation-config/>和<context:component-scanbase-package="需要实现注入的类所在包"/>,
可以使用base-package="*"表示全部的类。
< context:component-scan base-package=”com.eric.spring”>
其中base-package为需要扫描的包(含所有子包)
在接口前面标上@Autowired和@Qualifier注释使得接口可以被容器注入,当接口存在两个实现类的时候必须指定其中一个来注入,
使用实现类首字母小写的字符串来注入,如:
@Autowired
@Qualifier("chinese")
private Man man;
否则可以省略,只写@Autowired 。
@Service服务层组件,用于标注业务层组件,表示定义一个bean,自动根据bean的类名实例化一个首写字母为小写的bean,
例如Chinese实例化为chinese,如果需要自己改名字则:@Service("你自己改的bean名")。
@Controller用于标注控制层组件(如struts中的action)
@Repository持久层组件,用于标注数据访问组件,即DAO组件
@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
@Service
public class VentorServiceImpl implements iVentorService {
}
@Repository
public class VentorDaoImpl implements iVentorDao {
}
getBean 的默认名称是类名(头字母小写),如果想自定义,可以@Service(“aaaaa”) 这样来指定,这种
bean默认是单例的,如果想改变,可以使用@Service(“beanName”)@Scope(“prototype”)来改变。
可以使用以下方式指定初始化方法和销毁方法(方法名任意):
@PostConstruct
public void init() {
}
@PreDestroy
public void destory() {
}
Spring中@Autowired注解、@Resource注解的区别
BY ETHAN ON 2011年 06 月 02 日 IN JAVA
Spring不但支持自己定义的@Autowired注解,还支持几个由JSR-250规范定义的注解,它们分别是@Resource、@PostConstruct以及@PreDestroy。
@Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入,而@Resource默认按 byName自动注入罢了。@Resource有两个属性是比较重要的,分是name和type,Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。
@Resource装配顺序
1. 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
2. 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常
3. 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
4. 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;
@Autowired 与@Resource的区别:
1、 @Autowired与@Resource都可以用来装配bean.都可以写在字段上,或写在setter方法上。
2、 @Autowired默认按类型装配(这个注解是属业spring的),默认情况下必须要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,如:@Autowired(required=false),如果我们想使用名称装配可以结合@Qualifier注解进行使用,如下:
|
|
|
|
3、@Resource(这个注解属于J2EE的),默认安装名称进行装配,名称可以通过name属性进行指定,如果没有指定name属性,当注解写在字段上时,默认取字段名进行安装名称查找,如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。
|
| |
|
|
推荐使用:@Resource注解在字段上,这样就不用写setter方法了,并且这个注解是属于J2EE的,减少了与spring的耦合。这样代码看起就比较优雅。
简单讲讲@SpringBootApplication
1前言
在hello world中已经启动了一个最精简的springboot 应用.从我们编写的代码来看,它与非spring boot应用区别有两个地方:
(1)在QuickStartApplication
类上添加了注解@SpringBootApplication
;
(2)是main方法调用SpringApplication.run(QuickStartApplication.class,args)
这篇博客主要分享第一点,注解@SpringBootApplication
.分享的时候,我也是按照自己阅读源码的方式(每个人都有自己方法,方式.不喜勿噴).
2进入主题
我用IDEA进行开发,所以使用快捷键也是IDEA的.下面就是demo里代码
@SpringBootApplication
public class QuickStartApplication {
public static void main(String[]args){
SpringApplication.run(QuickStartApplication.class,args);
}
}
进入到@SpringBootApplication
的源码,可以看到里面组合了三个我们感兴趣的注解:@ComponentScan
,@EnableAutoConfiguration
,@SpringBootConfiguration
.我们一一分析这三个注解.
2.1@ComponentScan
使用过spring框架的小伙伴都知道,spring里有四大注解:@Service
,@Repository
,@Component
,@Controller
用来定义一个bean.@ComponentScan
注解就是用来自动扫描被这些注解标识的类,最终生成ioc容器里的bean.可以通过设置@ComponentScan
basePackages,includeFilters,excludeFilters属性来动态确定自动扫描范围,类型已经不扫描的类型.默认情况下:它扫描所有类型,并且扫描范围是@ComponentScan
注解所在配置类包及子包的类,在hello word 工程里,添加了一个componentscan 分支,说明这个情况.QuickStartApplication
,CurrentPackageController
类的package是com.simos.componentscan
.SubPackageController
的package 是com.simos.componentscan.controller
.而OutPackageController
的package是com.simos.controller
.启动后只有:SubPackageController
,CurrentPackageController
被扫描生成bean,而OutPackageController
却没有被扫描到.下面三个截图说明了这一点:
current.png
sub.png
out.png
总结一下,使用@SpringBootApplication
注解,就说明你使用了@ComponentScan
的默认配置,这就建议你把使用@SpringBootApplication
注解的类放置在root package(官方表述)下,其他类都置在root package的子包里面,这样bean就不会被漏扫描.
2.2@SpringBootConfiguration
这个注解的作用与@Configuration
作用相同,都是用来声明当前类是一个配置类.可以通过@Bean
注解生成IOC容器管理的bean.在QuickStartApplication
中定义bean,并在@HelloController
中注入使用
@SpringBootApplication
public class QuickStartApplication {
public static void main(String[]args){
SpringApplication.run(QuickStartApplication.class,args);
}
@Bean
public BeanTest beanTest(){
return new BeanTest();
}
}
下面是@HelloController
@RestController
public class HelloController {
@Autowired
BeanTest beanTest;
@RequestMapping(value = "/hello",method = RequestMethod.GET)
public String hello(){
return "hello world!";
}
@RequestMapping(value = "/beantest",method = RequestMethod.GET)
public String beanTest(){
return "beanTest!";
}
}
2.3@EnableAutoConfiguration
@EnableAutoConfiguration
是springboot实现自动化配置的核心注解,通过这个注解把spring应用所需的bean注入容器中.@EnableAutoConfiguration
源码通过@Import
注入了一个ImportSelector
的实现类AutoConfigurationImportSelector
,这个ImportSelector
最终实现根据我们的配置,动态加载所需的bean.
'AutoConfigurationImportSelector'的完成动态加载实现方法源码如下:
@Override
//annotationMetadata 是@import所用在的注解.这里指定是@EnableAutoConfiguration
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
//加载XXConfiguration的元数据信息(包含了某些类被生成bean条件),继续跟进这个方法调用,就会发现加载的是:spring-boot-autoconfigure jar包里面META-INF的spring-autoconfigure-metadata.properties
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
//获取注解里设置的属性,在@SpringBootApplication设置的exclude,excludeName属性值,其实就是设置@EnableAutoConfiguration的这两个属性值
AnnotationAttributes attributes = getAttributes(annotationMetadata);
//从spring-boot-autoconfigure jar包里面META-INF/spring.factories加载配置类的名称,打开这个文件发现里面包含了springboot框架提供的所有配置类
List<String> configurations = getCandidateConfigurations(annotationMetadata,
attributes);
//去掉重复项
configurations = removeDuplicates(configurations);
//获取自己配置不需要生成bean的class
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
//校验被exclude的类是否都是springboot自动化配置里的类,如果存在抛出异常
checkExcludedClasses(configurations, exclusions);
//删除被exclude掉的类
configurations.removeAll(exclusions);
//过滤刷选,满足OnClassCondition的类
configurations = filter(configurations, autoConfigurationMetadata);
fireAutoConfigurationImportEvents(configurations, exclusions);
//返回需要注入的bean的类路径
return StringUtils.toStringArray(configurations);
}
3小结
通过第二节我们可以看到,springboot是通过注解@EnableAutoConfiguration
的方式,去查找,过滤,加载所需的configuration
,@ComponentScan
扫描我们自定义的bean,@SpringBootConfiguration
使得被@SpringBootApplication
注解的类声明为注解类.因此@SpringBootApplication
的作用等价于同时组合使用@EnableAutoConfiguration
,@ComponentScan
,@SpringBootConfiguration
.