关于spring@Resource注解的问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于spring@Resource注解的问题相关的知识,希望对你有一定的参考价值。

这个注解是不是只能用于往<bean>注入实例 就像 name=“xxx” ref=“xxx”

如果我有个类 就只有一个数据
@Resource
string nn=“9090”;
假设 配置是<bean name="nn"class=""/>
是不是无法用

参考技术A 没错!!这是正确的哦,@Resource是相当于applicationContext.getBean方法!
这总体来说,是Spring依赖注入的两种写法,一种是注释的,一种是XML的写法!
前提是,只要你已经用@Component 注释了需要注入的对象,或者已经在XML文件中使用 bean 配置了需要注入的对象,你就可以用 @Resource 或者 applicationContext.getBean方法去注入这个对象!所以这两个,你可以任选一个。实际应用中,我们都是用@Resource这个办法。极少使用applicationContext.getBean方法。

当然,使用@Resource 注入的时候,还需要在XML中配置自动扫描的包哦,一般我们用Junit测试时候都用applicationContext.getBean 方法去注入,而不用@Resource 是因为我们的XML没有配置也扫描Junit的包。

希望能帮到你。
求采纳为满意回答。

关于spring事务注解实战

1.概述

spring的事务注解@Transaction 相信很多人都用过,而@Transaction 默认配置适合80%的配置。

本篇文章不是对spring注解事务做详细介绍,而是解决一些实际场景下遇到的问题

spring事务注解的基本原理

下面针对是否需要开启事务和是否需要回滚事务在特定场景下的介绍

2.事务回滚

2.1 默认回滚策略

@Transactional
public void rollback() throws SQLException {
    // update db
    throw new SQLException("exception");
}


上述代码事务会回滚吗?不会的,就算抛出SQLException了,但是之前的数据库操作依然会提交,原因就是@Transactional默认情况下只回滚RuntimeException和Error。

2.2 指定回滚异常

因此,如果要指定哪些异常需要回滚,则通过配置@Transactional中rollbackFor,例如

@Transactional(rollbackFor = {SQLException.class})
public void rollback() throws SQLException {
    // update db
    throw new SQLException("exception");
}

按照上面例子,那指定的SQLException,当抛出RuntimeException的时候,还会回滚吗?

@Transactional(rollbackFor = {SQLException.class})
public void rollback() throws SQLException {
    // update db
    throw new Runtime("exception");
}

还是会回滚的。

2.3 事务嵌套的回滚

假设有下面的逻辑,事务会回滚吗(或者说 updateA,updateB,updateC)哪些更新会提交

@Transactional
public void rollback() {
    // updateA
    try{
        selfProxy.innelTransaction()
    }catch(RuntimeException e){
        //do nothing
    }
    //updateC
}
 
@Transactional
public void innelTransaction() throws SQLException {
    // updateB
    throw new RuntimeException("exception");
}

 

答案是会回滚,因为内部事务触发回滚,当前事务被标记为 rollback-only,

当外部事务提交的时候,Spring抛出以下异常,同时回滚外部事务

org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
 

2.4 小结

所以,在需要事务回滚的时候,最好还是抛出RuntimeException,并且不要在代码中捕获此类异常

三、事务传播性

@Transaction中的propagation的可以配置事务的传播性,网上介绍的很多,就直接复制一段

PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。 (也是默认策略)
PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。 
PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。 
PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。 
PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 
PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。

3.1 如何在事务中读取最新配置

有时候需要在一个事务中,读取最新数据(默认是读取事务开始前的快照)。其实很简单,只要使用上面PROPAGATION_NOT_SUPPORTED传播性就可以了。

@Transactional
public void transaction() throws SQLException {
    // do something
    selfProxy.queryNewValue();
}
 
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void queryNewValue() throws SQLException {
    //查询数据中的最新值
} 

 

四、内部调用事务方法

事务注解的实质就是在创建一个动态代理,在调用事务方法前开启事务,在事务方法结束以后决定是事务提交还是回滚。

因此,直接在类内部中调用事务方法,是不会经过动态代理的

 

。 因此,如果要使方法B点事务生效,必须这样 

 

 

4.1 解决办法

解决思路:需要在内部调用方法B的时候,找到当前类的代理类,用代理类去调用方法B

4.1.1 解决办法1

 
@Service
public class MyService{
    @Transactional
    public void transaction(){
        // do something
        ((MyService) AopContext.currentProxy()).queryNewValue();
    }
     
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void queryNewValue(){
        //查询数据中的最新值
    }
}


通过AopContext.currentProxy()可以拿到当前类的代理类,但是要使用这个时候,必须在启动类上加上

@EnableAspectJAutoProxy(exposeProxy=true)

4.1.2 解决办法2

既然是要拿到当前代理类,那其实直接在Spring的容器里面去拿也可以啊。在spring中拿Bean的方法大致有2种

通过注入

@Service
public class MyService{
    @Autowired
    private MyService self;
    @Transactional
    public void transaction() {
        // do something
        self.queryNewValue();
    }
     
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void queryNewValue() {
        //查询数据中的最新值
    }
}

tips:spring现在对一些循环依赖是提供支持的,简单来说,满足:

  1. Bean是单例
  2. 注入的方式不是构造函数注入

通过BeanFactory

 

@Service
public class MyService implements BeanFactoryAware{
    private MyService self;
     
    @Transactional
    public void transaction(){
        // do something
        self.queryNewValue();
    }
     
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void queryNewValue() {
        //查询数据中的最新值
    }
     
     @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        self = beanFactory.getBean(MyService.class);
    }
}

 

4.2 需要注意的地方

    • 使用@Transaction注解的方法,必须用public来修饰。
    • 其实不止是@Transaction,其他类似@Cacheable,@Retryable等依赖spring proxy也必须使用上述方式达到内部调用。
    • @Transactional,@Async放在同一个类中,如果使用Autowire注入会循环依赖,而使用BeanFactoryAware会使得@Transactional无效

以上是关于关于spring@Resource注解的问题的主要内容,如果未能解决你的问题,请参考以下文章

Spring Resource框架体系介绍

[spring]@Resource和@Autowired区别对比

关于hibernate注解的问题

关于spring mvc 3.0注解,注入失败的问题

关于注解的一些看法

关于ssm的注解问题-@Autowired和@Resource的区别