抽象类不能实例化
但是我看有用法,abstract class 上用@Component注解
怎么理解
实例化都不行,怎么有bean?
抽象类不能实例化
但是我看有用法,abstract class 上用@Component注解
怎么理解
实例化都不行,怎么有bean?
除一楼提到的@Component + @Lookup适配单例Bean依赖多例Bean的问题,我想大多数都是为了在抽象类注入依赖,但实际上,只要抽象类有子类并且子类能正常注入IOC,捎带着抽象类本身所依赖的Bean也间接注入了,无需在抽象类本身加@Component; 我们甚至可以将Service依赖的所有Bean,统一注入到一个抽象类中,然后让Service继承这个抽象类,如此,这些Service就不用再单独声明它的依赖了
4 回答968 阅读
4 回答870 阅读
584 阅读
488 阅读
首先有一点我不太认同,抽象类不能实例化不假,但是不能直接说抽象类不能变为
bean。毕竟spring实例化bean的方式也不是说简单就是new一个嘛,靠的是代理类代理的方式实例化的。当然我们平常开发,起码自己来说,确实没有做过直接在抽象类或者接口上加
@Component,但是既然有人这么写过,说不定有一些特殊的用法。带着疑问我再回顾了一下源码,主要找的方向着重放在扫描有
@Component注解时有没有一些特殊的判断,来帮助我理解一下spring的逻辑从

ClassPathBeanDefinitionScanner扫描bean路径的doScan(String... basePackages)方法中可以看到如何挑选候选@Component组件的入口方法findCandidateComponents再进入其中,到了

ClassPathBeanDefinitionScanner的父类ClassPathScanningCandidateComponentProvider,进入到scanCandidateComponents方法这里面就有个判断是否是候选

@Component组件的关键方法isCandidateComponent(AnnotatedBeanDefinition beanDefinition)这里面的判断咱们可以捋一捋。翻译过来就是

这下有意思了,原来判断候选
@Component组件的标准里,是允许有抽象的类,也就是接口和抽象类都是可以加@Component注解的,只是呢,还有一个额外条件,必须其中至少还有一个方法带有@Lookup注解好吧,最后断案了,不过我之前是没怎么用过
@Lookup注解,看了一些用法后,明白了,这就是一个解决如何优雅的在单例bean中使用一个多例bean。比如
A中注入一个B,A单例,B多例当
A调用print方法时实际希望每次使用的b都是一个新实例,但是此时这样@Autowired做是达不到效果的,毕竟A是单例,所以生成的A的实例只会被创建一次,所以里面被注入的B也只是一个不会变了。想要达到多例的效果就是
print方法调用时,每次的b都是再次从BeanFactory中拿出来的就可以了。当然这里方法就很多了,你可以用
A去实现ApplicationContextAware接口,这样你可以为所欲为,但是这样代码比较重,毕竟ApplicationContext的概念和BeanFactory的概念在范围上还是有很大的差别你也可以做自己的实现自己的
BeanFactoryAware,这样你有了自己的BeanFactory的静态工具,print方法中就可以直接使用了铛铛铛,回到正题,当然最后你还可以借助

@Lookup注解啦,打开@Lookup类注释第一句话已经说明了它的用意翻译过来就是说,只要是加了
@Lookup注解的方法,容器会自动帮你覆盖实现,改为调用BeanFactory的getBean方法所以
A可以这样写这样就可以实现效果了,诶,不过好像说了半天没有说到抽象类上,只是提到了
@Lookup。但其实到这里就可以看到啦,这种实现效果是可以,不过写法是有够丑。return null是什么鬼,不知道@Lookup的同事可能看到这样的代码以为是谁在开始挖坑了呢。而且呢,之前的写法如果假设
C类中也要注入了B,也想要达到类似的效果岂不是C中也有一个类似的getB方法么?这显然有点重复代码的意味了。所以最终
spring团队思考了半个月,做出了一个违背。。。不好意思串台了。这时候咱们抽象类的抽象方法不就可以把这种空虚的实现给屏蔽掉了嘛
咱们都可以直接整一个接口
BCreatorA就可以改为,这样就真的看起来舒服多了(抽象类同理)好吧,上面就是我简单看法,不管题主懂了没,我是真顺道懂了不少,感谢题主问题的款待ヾ(≧▽≦*)o!