当前位置: 首页 > 后端技术 > Java

Spring——依赖注入还是方法注入?

时间:2023-04-01 13:58:26 Java

DependencyInjection我们在Spring中谈到了Spring的两种依赖注入方式——CircularDependencyConstructorInjectionPropertyInjection(setter注入也属于这个)@ServicepublicclassHelloService{/***PropertyInjection*/@AutowiredprivateBeanFactorybeanFactory;/***构造函数注入*/publicHelloService(ApplicationContextapplicationContext){}/***属性注入**/@AutowiredpublicvoidsetEnvironment(Environmentenvironment){System.out.println("");}}关于constructor实例化策略的文章在Spring源码里已经讲过了——Bean实例化和Spring实例化——谁是我的候选人?相同?其实对于Spring来说也是一样的,就是一个注入元素。AutowiredAnnotationBeanPostProcessor#postProcessProperties在bean实例化后调用此方法。那么构造函数注入和属性注入有什么区别,适用场景有哪些呢?构造函数注入的时机早于属性注入,并且是强依赖的。对于那些非必需的依赖,建议使用属性注入的方式来注入Lookup方法。注入的本质其实就是Spring继承你当前的类,通过CGLib生成子类,并重写需要注入的方法。也许这还不清楚,那么让我们看一个例子@Service@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)publicclassPrintService{privateintprintCount;publicvoidprint(Stringname){System.out.println("hi!"+name+""+printCount++);}}@ServicepublicclassHelloService{@AutowiredprivatePrintServiceprintService;publicvoidsayHi(Stringname){printService.print(name);}}PrintService是原型类型的bean,HelloService是单例,我的初衷是每次调用sayHi方法时使用一个新创建的PrintService对象,但是单纯的属性注入或者构造函数注入是无法实现的。或许你会想到每次使用PrintService时都使用ApplicationContext/BeanFactory在Spring中获取,这样每次都能获取到一个新创建的实例。这当然是可以的,但是既然逻辑是这样的,那框架能不能帮我们做呢?当然可以@ServicepublicclassHelloService{publicvoidsayHi(Stringname){getPrintService().print(name);}@Lookup("printService")protectedPrintServicegetPrintService(){返回空;}}@Lookup修饰的方法必须被子类重写。如果beanName没有设置@Lookup注解,那么会根据方法返回类型从Spring获取beanpublic@interfaceLookup{Stringvalue()default"";}这段代码其实在Spring源码中——-Bean实例化和Spring实例化--我的候选人谁以前遇到过,只是没有点进去详细了解。如果你用@Lookup修饰的方法的类是通过配置类实例化的,那么这个注解就会失效。只有通过构造函数实例化的beans才能由Spring处理并使用CGLib进行子类化。第二种MethodReplacer是MethodReplacerpublicclassLookupMethodBean{publicvoidtest(){System.out.println("原始方法!");}}publicclassMethodReplaceimplementsMethodReplacer{publicObjectreimplement(Objectobj,Methodmethod,Object[]args)throwsThrowable{System.out.println("该方法已被替换!");返回空值;,只是原来的xml配置原理和Lookup是一样的,是不是很像AOP,其实又不一样,永远不能用MethodReplacer回调重写的方法,完全覆盖,不像AOP,可以拦截之前和之后。所以在实际业务中,可以用到这个MethodReplacer的地方很少,会用到它的AOP就可以做到,甚至比它灵活多了。今天的文章就到这里啦~~本文由博文多发平台OpenWrite发布!