Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 弹簧自注入_Java_Spring_Dependency Injection_Ioc Container - Fatal编程技术网

Java 弹簧自注入

Java 弹簧自注入,java,spring,dependency-injection,ioc-container,Java,Spring,Dependency Injection,Ioc Container,我用Spring 3.x尝试了以下代码,但失败了BeanNotFoundException,应该是根据我之前问过的一个问题的答案- 由于我在Java 6中尝试了这一点,我发现以下代码可以正常工作: @Service(value = "someService") public class UserService implements Service{ @Resource(name = "someService") private Service self; } 但我不明白它是如何

我用Spring 3.x尝试了以下代码,但失败了
BeanNotFoundException
,应该是根据我之前问过的一个问题的答案-

由于我在Java 6中尝试了这一点,我发现以下代码可以正常工作:

@Service(value = "someService")
public class UserService implements Service{
    @Resource(name = "someService")
    private Service self;
}
但我不明白它是如何解决循环依赖的

编辑:
这是错误消息。OP在对其中一个答案的评论中提到了这一点:

原因:org.springframework.beans.factory.NoSuchBeanDefinitionException:找不到依赖项类型为[com.spring.service.service]的匹配bean:至少需要1个符合此依赖项autowire候选项条件的bean。依赖项注释:{@org.springframework.beans.factory.annotation.Autowired(required=true)}


给出上述代码,我看不到循环依赖关系。 您将服务的某个实例注入到UserService中。 注入服务的实现不一定需要是另一个UserService,因此不存在循环依赖关系


我不明白为什么要将UserService注入UserService,但我希望这是一次理论上的尝试。

看起来spring创建并配置了一个对象,然后将其放在bean查找上下文中。但是,在Java的情况下,我认为它创建了对象,并将其与名称和配置绑定在一起,当通过在上下文中找到的名称查找对象时

此代码也适用:

@Service
public class UserService implements Service {

    @Autowired
    private ApplicationContext applicationContext;

    private Service self;

    @PostConstruct
    private void init() {
        self = applicationContext.getBean(UserService.class);
    }
}
我不知道为什么,但是Spring似乎可以从
ApplicationContext
获取bean,如果它是创建的,但没有初始化
@Autowired
在初始化之前工作,它找不到相同的bean。因此,
@Resource
可能在
@Autowired
之后和
@PostConstruct
之前工作


但我不知道,只是猜测而已。无论如何,好问题。

更新:2016年2月

SpringFramework4.3将正式支持自动布线。从这一点可以看出实施情况


无法自动连线的最终原因是Spring的
DefaultListableBeanFactory.FinDautoWire候选(字符串、类、DependencyDescriptor)
方法的实现明确排除了这种可能性。从该方法的以下代码摘录中可以看到这一点:

for (String candidateName : candidateNames) {
    if (!candidateName.equals(beanName) && isAutowireCandidate(candidateName, descriptor)) {
        result.put(candidateName, getBean(candidateName));
    }
}
仅供参考:bean的名称(即尝试自动连接自身的bean)是
beanName
。该bean实际上是一个autowire候选者,但上面的if条件返回false(因为
candidateName
实际上等于
beanName
)。因此,您无法将bean与自身自动关联(至少在Spring3.1M1中是这样)

现在,从语义上讲,这是否是有意的行为,这是另一个问题

我去问问尤尔根,看看他有什么话要说

问候,

Sam(核心弹簧提交人)


我已经打开了一个Spring JRRA问题,考虑使用@ AutoRoD支持类型自动自偿。请随意观看或投票:顺便说一下,对于自调用问题,更优雅的解决方案是使用AspectJ加载时编织用于事务代理(或使用AOP引入的任何代理)

例如,对于注释驱动的事务管理,您可以使用“aspectj”模式,如下所示:

<tx:annotation-driven mode="aspectj" />

请注意,默认模式是“代理”(即JDK动态代理)

问候,

Sam

问题建议使用适用于特殊情况的AopContext.currentProxy()替代黑客方法。

仅是另一种方法:

@EnableAsync
@SpringBootApplication
public class Application {

    @Autowired
    private AccountStatusService accountStatusService;

    @PostConstruct
    private void init() {
        accountStatusService.setSelf(accountStatusService);
    }
}

@Service
public class AccountStatusService {
    private AccountStatusService self;

    public void setSelf(AccountStatusService self) {
        this.self = self;
    }
}
这样,您的服务将成为代理。我这样做是为了在其内部使用异步方法

我尝试过@sinuhepop解决方案:

@PostConstruct
private void init() {
    self = applicationContext.getBean(UserService.class);
}

它进行了注入,但服务不在代理内,我的方法也没有在新线程上运行。这是我为中小型项目提供的解决方案。没有AspectJ或应用程序上下文魔术,它与单例和构造函数注入一起工作,并且非常容易测试

@Service
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
class PersonDao {

    private final PersonDao _personDao;

    @Autowired
    public PersonDao(PersonDao personDao) {
        _personDao = personDao;
    }
}

我只有一个服务实现,那就是UserService:)。。相同的代码在Spring@Autowired中失败,但在@resource中工作如果服务在其周围使用Spring缓存代理,并且您希望内部调用从该缓存中受益,那么将bean连接到自身可能很有用。aspectj可以与JDK代理一起工作吗?我想它需要CGLib,对吗?aspectj处理自调用,但会产生其他问题,而且上次我检查时不推荐使用SpringSource文档。@Amit-这确实解释了!!它们只排除自动连接的候选对象,而不检查其他候选对象,如@Resource等。我认为这样的方法在某些情况下非常有用,例如,有时需要使用事务代理(特别是requires_new)包装方法,该代理可以自调用。必须“分离”这样的功能通常会导致反模式和糟糕的设计。与NVR一致,同一类
@Transactional
代理是导致我出现这种情况的原因。当您有一个成熟的代码库时,“使用AspectJ而不是CGLib”不是一个有用的答案。使用
@Resource
可能会解决我的问题,但
@Autowired
更可取,因为这是我们的标准。@Xiangyu,Juergen Hoeller三天前刚刚记录了这一点:记住添加
@Lazy
很酷,将上下文注入到应用程序bean中。这是有史以来最好的实践@avrilfanomar:好吧,如果一个类需要意识到它本身有一个代理,那么无论如何你都在破坏DI抽象,所以我认为访问你的容器并不是更糟。为什么它会破坏DI?我认为注入self并没有什么坏处,比如说,它应该使用事务性方法。我在上面用UserService类中的更多字段做了同样的尝试。但当我做self.morefield.xxx时。它提出了一个问题:自我注入的目的是什么
@Service
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
class PersonDao {

    private final PersonDao _personDao;

    @Autowired
    public PersonDao(PersonDao personDao) {
        _personDao = personDao;
    }
}