服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|JavaScript|易语言|

服务器之家 - 编程语言 - JAVA教程 - 浅谈spring 常用注解

浅谈spring 常用注解

2021-02-03 11:52Justnow_ JAVA教程

这篇文章主要介绍了浅谈spring 常用注解,具有一定参考价值,需要的朋友可以了解下。

我们不妨先将spring常用的注解按照功能进行分类

1 、将普通类加入容器形成Bean的注解

日常开发中主要使用到的定义Bean的注解包括(XML方式配置bean暂不讨论):

@Component、@Repository、@Service、@Controller、@Bean

其中@Component、@Repository、@Service、@Controller实质上属于同一类注解,用法相同,功能相同,区别在于标识组件的类型。当一个组件代表数据访问层(Dao)时,你可以给它加上@Repository注解,如下例:

?
1
2
3
4
5
6
7
8
9
@Repository
public class BiliAPIDaoImpl implements BiliAPIDao {
private final static Logger LOGGER = LoggerFactory.getLogger(BiliAPIDaoImpl.class);
 
private BiliAPIHttpClient asoAPIHttpClient;
public void execute(){
  //some logic business
 }
}

当组件用于业务层时,使用@Service注解,如下例:

?
1
2
3
4
5
6
7
8
9
10
@Service(value="SecUserService")
public class SecUsersServiceImpl implements SecUsersService {
 @Autowired
 private SecUsersDao secUsersDao;
 @Autowired
 private SecRoleUserService secRoleUserService;
 public void doBusiness(){
  //do some business
 }
 }

注意,在此处的@Service注解中额外添加了value=”SecUserService”的属性,为何对此一举呢?value属性可以指定生成后Bean的名称,这个名称便成为容器中bean 的唯一标识符。同样的,在@Component、@Repository、@Controller也均可以指定其value值,当然,是如有必要时加

当组件属于控制层时,则使用@Controller注解;当组件不能进行很好地归类时,那我们可以使用@Component注解。因使用方式均相同,故此处不再继续贴代码

在这几个注解中,额外需要留意的是@Bean注解。不妨看代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@Component
public class FactoryMethodComponent {
 
 private static int i;
 
 @Bean @Qualifier("public")
 public TestBean publicInstance() {
  return new TestBean("publicInstance");
 }
 
 // use of a custom qualifier and autowiring of method parameters
 
 @Bean
 protected TestBean protectedInstance(@Qualifier("public") TestBean spouse,
          @Value("#{privateInstance.age}") String country) {
  TestBean tb = new TestBean("protectedInstance", 1);
  tb.setSpouse(tb);
  tb.setCountry(country);
  return tb;
 }
 
 @Bean @Scope(BeanDefinition.SCOPE_SINGLETON)
 private TestBean privateInstance() {
  return new TestBean("privateInstance", i++);
 }
 
 @Bean @Scope(value = WebApplicationContext.SCOPE_SESSION,
    proxyMode = ScopedProxyMode.TARGET_CLASS)
 public TestBean requestScopedInstance() {
  return new TestBean("requestScopedInstance", 3);
 }
}

Bean注解主要用于方法上,有点类似于工厂方法,当使用了@Bean注解,我们可以连续使用多种定义bean时用到的注解,譬如用@Qualifier注解定义工厂方法的名称,用@Scope注解定义该bean的作用域范围,譬如是singleton还是prototype等。

此处还得另外提一个注解: @Configuration.实际上,上面谈到的@Bean注解更多时候是与@Configuration注解在一起使用的。如果将一个类标注为@Configuration注解,那么也就意味着这个class将会作为创建各种bean的工厂(类似于一个新的容器)。最简单的配合使用示例如下:

?
1
2
3
4
5
6
7
@Configuration
public class AppConfig {
 @Bean
 public MyService myService() {
  return new MyServiceImpl();
 }
}

以上的代码实际上等价于Xml中的配置:

?
1
2
3
<beans>
 <bean class="com.acme.services.MyServiceImpl" id="myService">
</bean></beans>

我们还需要注意的一点,在Spring的@Component注解中使用@Bean与在Spring中的@Configuration使用是一定的差别的。在使用@Component的类中不会强制使用CGLIB代理拦截方法和属性。而在@Configuration类中,则会使用CGLIB代理去调用@Bean标注的方法并返回对象的引用。在@Configuration注解中使用@Bean也可以防止同一个@Bean方法被意外调用多次时而产生细微的难以排查的错误

2、从容器中取Bean(装配bean)时常用的注解

开发中最常用到的用于装配的注解是:@Autowired和@Resource

@Autowired注解:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class MovieRecommender {
 
 @Autowired
 private MovieCatalog movieCatalog;
 
 private CustomerPreferenceDao customerPreferenceDao;
 
 @Autowired
 public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
  this.customerPreferenceDao = customerPreferenceDao;
 }
 
 // ...
}

@Autowired注解可用于为类的属性、构造器、方法进行注值。默认情况下,其依赖的对象必须存在(bean可用),如果需要改变这种默认方式,可以设置其required属性为false。另外一个比较重要的点就是,@Autowired注解默认按照类型装配,如果容器中包含多个同一类型的Bean,那么启动容器时会报找不到指定类型bean的异常,解决办法是结合@Qualified注解进行限定,指定注入的bean名称

@Resource注解
对于@Resource注解,它并不属于spring的注解,而是来自于JSR-250。其默认情况下按照bean的名称进行注入,当找不到匹配项时会按照类型装配。当按照名称进行装配时,可以指定其name属性,倘若没有指定,注解标注在哪个字段上,其默认名称就是那个字段的名称。当然,@Resource注解也支持按指定类型进行装配,给它的type属性赋特定类型的值即可(注意,当指定了name属性后,只能按照名称装配)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
public class SpringAnotationDemo {
 
 @Bean
 @Qualifier("httpApiClient")
 public HttpApiClient createHttpClient() {
  return new HttpApiClient();
 }
 
 @Resource(name = "httpApiClient")
 private HttpApiClient httpApiClient;
 @Resource(type = XQSmsHttpClient.class)
 private SmsHttpClient smsHttpClient;
}

依我个人理解,其实@Resource要比@Autowired好用得多,@Resource注解的使用性更为灵活,可指定名称,也可以指定类型 ,而用@Autowired注解进行装配容易抛出异常,特别是装配的bean类型有多个的时候,而解决的办法是需要在增加@Qualitied进行限定

vc模块注解">3、spring MVC模块注解
web模块常用到的注解包括:

@Controller、@RequestMapping、@RequestParam、@PathVariable

@Controller
将一个类加上@Controller注解后,表明该类会作为与前端作交互的控制层组件

?
1
2
3
4
5
@Controller
public class CompanyController {
/**this class will be the controller component of container**/
...
}

@RequestMapping
这个注解用于将url映射到整个处理类或者特定的处理请求的方法

?
1
2
3
4
5
6
7
8
@Controller
@RequestMapping("/company")
public class CompanyController {
 
 @Autowired
 private CompanyService companyService;
...
}

如上例,当标注在class上时,表明此类会接收url为”/company”请求

@RequestParam
用于绑定request请求参数到指定的方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Controller
@RequestMapping("/company")
public class CompanyController {
 
 @Autowired
 private CompanyService companyService;
 
 @RequestMapping("/companyList")
 public String listCompanies(Map<string, object=""> map,
    @RequestParam(value = "data", required = false) String data,
    @RequestParam(value = "phone_num", required = true) String phoneNum) {
 map.put("data", data);
 map.put("phoneNum", phoneNum);
 return "companyList";
 }
...
}

譬如上例中,@RequestParam请求参数指定了传入参数的具体字段名(value指定的),以及是否必须传的字段(默认情况下,required=true)。data,phoneNum为形参,即请求参数的使用名,可以更改

@PathVariable
该注解用于方法修饰方法参数,会将修饰的方法参数变为可供使用的uri变量(可用于动态绑定),请看如下栗子:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Controller
@RequestMapping("/company")
public class CompanyController {
 
 @Autowired
 private CompanyService companyService;
 
 @RequestMapping("{companyName}")
 public String getCompany(Map<string, object=""> map,
   @PathVariable String companyName) {
 Company company = companyService.findByName(companyName);
 map.put("company", company);
 return "company";
 }
...
}

当我们请求 “/compony/account”时,componyName会动态地绑定为”account”

4、事务模块注解@Transactional

在处理dao层或service层的事务操作时,譬如删除失败时的回滚操作,可用到@Transactional注解,如下例:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
@Service
public class CompanyServiceImpl implements CompanyService {
 @Autowired
 private CompanyDAO companyDAO;
 
 @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)
 public int deleteByName(String name) {
 
 int result = companyDAO.deleteByName(name);
 return company;
 }
 ...
}

上例表明,执行deleteByName方法时,启用了事务处理,事务的各属性含义如下:

propagation
事务的传播行为,spring在TransactionDefinition接口中规定了7种类型的事务传播行为,它们规定了事务方法和事务方法发生嵌套调用时如何进行传播:

 

事务传播行为类型 描述
PROPAGATION_REQUIRED 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。
PROPAGATION_SUPPORTS 支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY 使用当前的事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW 新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER 以非事务方式执行,如果当前存在事务,则抛出异常
PROPAGATION_NESTED 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类 似的操作

 

注:第一种是最常用的,默认的

readOnly
事务的读写属性,取true或者false,true为只读、默认为false rollbackFor
回滚策略,当遇到指定异常时回滚。譬如上例遇到异常就回滚 timeout (补充的)
设置超时时间,单位为秒 isolation
设置事务隔离级别,枚举类型,一共五种

 

类型 描述
DEFAULT 采用数据库默认隔离级别
READ_UNCOMMITTED 读未提交的数据(会出现脏读取)
READ_COMMITTED 读已提交的数据(会出现幻读,即前后两次读的不一样)
REPEATABLE_READ 可重复读,会出现幻读
SERIALIZABLE 串行化(对资源消耗较大,一般不使用)

 

5、 Spring AOP模块注解
spring aop模块的注解主要有@Aspect、@Pointcut、@Before、@Around、@After、
@AfterReturning、@AfterThrowing

@Aspect
标明该类为切面类,并启用AspectJ注解,注:在使用时要同@Component一起使用,否则不会被扫描到加入容器

@Pointcut
定义切入点,关于切入点表达式书写方式,请移步官方文档:spring AOP文档

@Around
定义环绕通知,在目标方法执行前后嵌入相关业务逻辑

@Before
定义前置通知,在目标方法执行前执行

@After
定义后置通知,在目标方法执行后执行,不论是目标方法执行正常后退出,还是抛出异常后退出,均会被执行

@AfterReturning
目标方法执行正常退出后执行 @AfterThrowing
目标方法执行抛出异常后执行

总结

以上就是本文关于浅谈spring 常用注解的全部内容,希望对大家有所帮助。有什么问题可以随时留言,小编会及时回复大家的。感谢朋友们对本站的支持!

原文链接:https://www.2cto.com/kf/201609/546408.html

延伸 · 阅读

精彩推荐
  • JAVA教程Java 8 lambda表达式引入详解及实例

    Java 8 lambda表达式引入详解及实例

    这篇文章主要介绍了Java 8 lambda表达式引入详解及实例的相关资料,需要的朋友可以参考下 ...

    蹭饭熊5062020-11-01
  • JAVA教程快速排序的原理及java代码实现

    快速排序的原理及java代码实现

    网上关于快速排序的算法原理和算法实现都比较多,不过java是实现并不多,而且部分实现很难理解,和思路有点不搭调。所以整理了这篇文章。如果有不妥...

    hebedich1622020-03-26
  • JAVA教程spring配置扫描多个包问题解析

    spring配置扫描多个包问题解析

    这篇文章主要介绍了spring配置扫描多个包问题解析,具有一定参考价值,需要的朋友可以了解下。...

    微wx笑6662021-01-28
  • JAVA教程Java之递归求和的两种简单方法(推荐)

    Java之递归求和的两种简单方法(推荐)

    下面小编就为大家带来一篇Java之递归求和的两种简单方法(推荐)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    yigese4322020-06-16
  • JAVA教程浅谈Java后台对JSON格式的处理操作

    浅谈Java后台对JSON格式的处理操作

    下面小编就为大家带来一篇浅谈Java后台对JSON格式的处理操作。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧 ...

    jingxian3852020-05-09
  • JAVA教程java实现五子棋小游戏

    java实现五子棋小游戏

    这篇文章主要介绍了java实现五子棋小游戏的相关资料,十分简单实用,推荐给大家,需要的朋友可以参考下 ...

    hebedich1582019-12-14
  • JAVA教程jar包双击执行程序的方法

    jar包双击执行程序的方法

    这篇文章主要介绍了jar包双击执行程序的方法,可实现双击jar包直接执行Java程序的功能,具有一定的参考借鉴价值,需要的朋友可以参考下 ...

    shichen20146562019-12-07
  • JAVA教程java小数位的例子

    java小数位的例子

    在java中要保留数字小数位我们有常用的四种方法,分别为:四舍五入,DecimalFormat,format,String .format与struts标签操作实现,下面给出例子 ...

    java教程网4082019-10-20