共计 2339 个字符,预计需要花费 6 分钟才能阅读完成。
依赖注入
咱们在 Spring — 循环依赖 中谈到 Spring 的两种依赖注入形式
- 结构器注入
- 属性注入 (setter 注入也归属于此)
@Service | |
public class HelloService { | |
/** | |
* 属性注入 | |
*/ | |
@Autowired | |
private BeanFactory beanFactory; | |
/** | |
* 结构器注入 | |
*/ | |
public HelloService(ApplicationContext applicationContext) { } | |
/** | |
* 属性注入 | |
* */ | |
@Autowired | |
public void setEnvironment(Environment environment) {System.out.println(""); | |
} | |
} |
对于构造函数实例化策略的文章曾经在 Spring 源码 –Bean 实例化 和 Spring 实例化 – 谁是我的候选人 曾经谈及过
那么 @Autowired
放在属性上和放在 setter 办法上有什么不一样呢?其实对于 Spring 来说都是一样的、都是一个注入元素。
AutowiredAnnotationBeanPostProcessor#postProcessProperties 该办法在 bean 实例化之后被调用
那么构造函数注入和属性注入的差异和实用场景是啥?
- 构造函数注入注入的机会是先于属性注入的、并且是强依赖的
- 对于那些非必须的依赖、举荐应用属性注入
办法注入
Lookup
办法注入的实质实际上是 Spring 继承你以后类、通过 CGLib 产生子类并且重写须要注入的办法。
可能这么说有的不明所以,看个例子
@Service | |
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) | |
public class PrintService { | |
private int printCount; | |
public void print(String name) {System.out.println("hi!" + name + " " + printCount++); | |
} | |
} | |
@Service | |
public class HelloService { | |
@Autowired | |
private PrintService printService; | |
public void sayHi(String name) {printService.print(name); | |
} | |
} |
PrintService 是一个 prototype 类型的 bean、HelloService 是一个 singleton、我的本意是每次调用 sayHi 办法的时候都能应用一个新创建的 PrintService 对象,然而单纯靠属性注入或者构造函数注入都是不可能实现的。
或者你可能会想到应用 ApplicationContext / BeanFactory 每次应用 PrintService 的时候去 Spring 中获取,这样子就能每次获取到一个新创建的实例。这样当然能够、然而既然逻辑都是这样、框架能不能帮咱们做呢?当然是能够的
@Service | |
public class HelloService {public void sayHi(String name) {getPrintService().print(name); | |
} | |
@Lookup("printService") | |
protected PrintService getPrintService(){return null;} | |
} |
@Lookup 润饰的办法必须是可被子类笼罩的、如果没有设置 beanName 给 @Lookup 注解、那么则依据办法返回类型从 Spring 中获取该 bean
public @interface Lookup {String value() default ""; | |
} |
这段代码其实咱们在 Spring 源码 –Bean 实例化 和 Spring 实例化 – 谁是我的候选人 已经遇到过、只是没有点进来具体理解。
如果你用 @Lookup 润饰的办法的类是通过配置类去实例化的话、那么这个注解则会生效。只有通过构造函数实例化的 bean 能力被 Spring 解决、应用 CGLib 产生子类。
MethodReplacer
第二种则是 MethodReplacer
<bean name="replacer" class="springroad.deomo.chap4.MethodReplace"> | |
</bean> | |
<bean name="testBean" class="springroad.deomo.chap4.LookupMethodBean"> | |
<replaced-method name="test" replacer="replacer"> </replaced-method> | |
</bean> |
public class LookupMethodBean {public void test() | |
{System.out.println("原始办法!"); | |
} | |
} | |
public class MethodReplace implements MethodReplacer {public Object reimplement(Object obj, Method method, Object[] args) | |
throws Throwable {System.out.println("办法曾经被替换!"); | |
return null; | |
} | |
} |
临时没有找到 MethodReplacer 相干的注解、只能用原始的 xml 配置
原理跟 Lookup 也是一样的
是不是跟 AOP 很像、然而其实是不一样的、MethodReplacer 你是永远没有方法调回被笼罩的办法的、它是齐全笼罩的、而不是像 AOP 那样能够前置后置拦挡。所以理论业务上很少中央能够用到这个 MethodReplacer、能用到它的 AOP 都能做到、甚至比它灵便太多
明天的文章就到这咯~~
本文由博客一文多发平台 OpenWrite 公布!