Spring方法注入

在spring中注入方式有3中:

1, 构造函数注入

2, set方法注入

3, 接口注入(方法注入)

在spring中的bean默认范围都是单例, 但是在特定的情况下, 我们需要有如下的业务需要, 单例bean1需要依赖非单例bean2, 由于bean1始终是单例,所以如果不做出改变,每次获取的bean2也是同一个, 容器就没办法给我们提供一个新的bean2.

spring提供了如下方法:

1, 非ioc, 通过bean1实现ApplicationContextAware接口, 利用ApplicatioinContext在需要的时候getBean("bean1");

2, lookup方式

3, 其他

常用的1、2种方式

利用非IOC方式:

1package org.xyz.svc.impl; 2 3import org.springframework.beans.BeansException; 4import org.springframework.context.ApplicationContext; 5import org.springframework.context.ApplicationContextAware; 6import org.xyz.svc.UserSvc; 7import org.xyz.vo.User; 8 9public class UserSvcImpl implements UserSvc, ApplicationContextAware{ 10 11 private ApplicationContext context; 12 13 @Override 14 public User initUser() { 15 return (User)context.getBean("User"); 16 } 17 18 @Override 19 public void setApplicationContext(ApplicationContext context) 20 throws BeansException { 21 this.context = context; 22 } 23 24}

applicationContext.xml :

1<?xml version="1.0" encoding="UTF-8"?> 2<!-- 3 - Middle tier application context definition for the image database. 4 --> 5<beans xmlns="http://www.springframework.org/schema/beans" 6 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 7 xmlns:context="http://www.springframework.org/schema/context" 8 xmlns:tx="http://www.springframework.org/schema/tx" 9 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 10 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd 11 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> 12 <bean name = "User" class = "org.xyz.vo.User" scope="prototype"></bean> 13 14 <bean name="UserSvc" class = "org.xyz.svc.impl.UserSvcImpl"> 15 </bean> 16 17</beans>

TestCase:

1package test; 2 3import org.junit.Before; 4import org.junit.Test; 5import org.springframework.context.ApplicationContext; 6import org.springframework.context.support.ClassPathXmlApplicationContext; 7import org.xyz.svc.UserSvc; 8 9public class TestUserSvc { 10 11 private ApplicationContext applicationContext; 12 13 @Before 14 public void init() throws Exception{ 15 applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); 16 } 17 18 @Test 19 public void testProcess(){ 20 UserSvc userSvc = (UserSvc)applicationContext.getBean("UserSvc", UserSvc.class); 21 22 System.out.println(userSvc.initUser()); 23 System.out.println(userSvc.initUser()); 24 System.out.println(userSvc.initUser()); 25 } 26 27}

运行结果:

1org.xyz.vo.User@10f6d3 2org.xyz.vo.User@1bcc0bc 3org.xyz.vo.User@111a3a4

这种方式还是与spring framework产生了耦合,可以看到获取User的时候,指定了bean2的名称.

推荐使用下面的lookup方式实现, 因为这种方式使用了代理,spring利用cglib生成了需要的子类.

 去掉实现接口ApplicationContextAware, 定义抽象获取user的的方法为抽象方法

1package org.xyz.svc.impl; 2 3import org.xyz.svc.UserSvc; 4import org.xyz.vo.User; 5 6public abstract class UserSvcImpl implements UserSvc{ 7 8 public User initUser() { 9 return createUser(); 10 } 11 12 public abstract User createUser(); 13 14}

applicationContext.xml

1<?xml version="1.0" encoding="UTF-8"?> 2<!-- 3 - Middle tier application context definition for the image database. 4 --> 5<beans xmlns="http://www.springframework.org/schema/beans" 6 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 7 xmlns:context="http://www.springframework.org/schema/context" 8 xmlns:tx="http://www.springframework.org/schema/tx" 9 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 10 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd 11 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> 12 <bean name = "User" class = "org.xyz.vo.User" scope="prototype"></bean> 13 14 <bean name="UserSvc" class = "org.xyz.svc.impl.UserSvcImpl"> 15 <lookup-method name="createUser" bean="User"/> 16 </bean> 17 18</beans>

TestCase

运行结果:

1org.xyz.vo.User@6f50a8 2org.xyz.vo.User@187814 3org.xyz.vo.User@73a7ab

实现了我们想要的需求了.

注意:  被注入的方法定义要求: 

<public|protected> [abstract] <return-type> theMethodName(no-arguments);

如果是抽象方法,会被spring动态生产的子类实现,如果不是抽象,会被覆盖. 所以类和方法修饰符不可以为final.

点赞
收藏

评论区

加载中...

相关推荐

从源码层面深度剖析Spring循环依赖

作者:郭艳红以下举例皆针对单例模式讨论图解参考1、Spring如何创建Bean?对于单例Bean来说,在Spring容器整个生命周期内,有且只有一个对象。Spring在创建Bean过程中,使用到了三级缓存,即DefaultSingletonBeanRegi

SpringIOC官方文档解读

IoC容器本章介绍了Spring的控制反转(IoC)容器。1.1。SpringIoC容器和Bean简介本章介绍了反转控制(IoC)原则的Spring框架实现。IoC也称为依赖注入(DI)。在此过程中,对象可以通过①构造函数参数(),②工厂方法的参数③或在构造或从工厂方法返回后在对象实例上设置的属性来定义其依

Spring一些问题记录

1、在非springbean中注入bean        在项目中有时需要根据需要在自己new一个对象,或者在某些util方法或属性中获取SpringBean对象,从而完成某些工作,但是由于自己new的对象和util方法并不是受Spring所管理的,如果直接在所依赖的属性上使用@Autowired就会报无法注入的错误,或者是没报错,但是使用的时候会

Spring 必知概念(二)

13、Spring框架中的单例Beans是线程安全的么?Spring框架并没有对单例bean进行任何多线程的封装处理。关于单例bean的线程安全和并发问题需要开发者自行去搞定。但实际上,大部分的Springbean并没有可变的状态(比如Serview类和DAO类),所以在某种程度上说Spring的单例bean是线程安全的。如果你的bean有多

Spring容器中Bean的作用域

当通过Spring容器创建一个Bean实例时,不仅可以完成Bean实例的实例化,还可以为Bean指定特定的作用域。Spring支持如下5种作用域:singleton:单例模式,在整个SpringIoC容器中,使用singleton定义的Bean将只有一个实例prototype:原型模式,每次通过容器

Spring3.1.0实现原理分析(八).获取bean对象

   Spring获取bean对象的逻辑相对简单,原本不打算专门写篇博客来介绍了。不过想了想,既然上两篇博客分析了Spring创建对象的过程,有创建便有获取,所以还是分析下获取bean对象的过程吧。一.获取单例bean1).进入DefaultSingletonBeanRegistry的getSingleton方法,下面是代码片段,简单