用spring做领域对象的依赖注入
2017-06-12 00:00
232 查看
依赖注入是现在一个使用非常广泛的技术,极大的降低了编写程序的难度。对于领域层的代码,我们也想使用依赖注入。对于无状态的service repository factory等对象,我们可以用spring容器初始化它们,把它们作为普通的spring的bean,这样它们天生就能被注入依赖了。对于entity, value objects这些有状态的对象,依赖注入就有点麻烦了。
这样不仅代码量大,而且不灵活,如果以后C需要注入其它依赖,所有初始它的地方都要多写很多代码。因此,我们需要spring能够帮助我们自动注入依赖。通过下面的代码可以完成:
通过调用autowire方法,会自动根据对象里的@Autowired注入依赖,如下:
这样不论C的依赖要求如何变化,CFactory里面都只要注入autowireInjector就行了。改了C不需要动CFactory。
这样,只要Factory和Repository以Factory和Repository作为类名的后缀,以create find作为方法的前缀,其返回值就会被注入依赖,而且支持返回领域对象集合。那此不通过Factory和Repository创建的对象,还是须要手动的注入依赖。
然后通过spring,把它配置到SessionFactory里面:
这样,在post-load和merge的时候,会注入依赖。对于@Embedded的对象,这样是不管用的,还没有找到更好的办法。
让spring帮我们注入依赖
如果手动注入依赖,会很麻烦,如下:public class CFactory { private A a; private B b; public C creaetC() { C c = new C(); //手动注入依赖 c.setA(a); c.setB(b); return c; } @Autowired public void setA(A a) { this.a = a; } @Autowired public void setB(B a) { this.b = b; } }
这样不仅代码量大,而且不灵活,如果以后C需要注入其它依赖,所有初始它的地方都要多写很多代码。因此,我们需要spring能够帮助我们自动注入依赖。通过下面的代码可以完成:
public class AutowireInjector implements ApplicationContextAware { private ApplicationContext applicationContext; public void autowire(Object bean) { this.applicationContext.getAutowireCapableBeanFactory().autowireBean(bean); } public void autowireBeanProperties(Object existingBean, int autowireMode, boolean dependencyCheck) { this.applicationContext.getAutowireCapableBeanFactory().autowireBeanProperties(existingBean, autowireMode, dependencyCheck); } public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } }
通过调用autowire方法,会自动根据对象里的@Autowired注入依赖,如下:
public class C { private A a; private B b; @Autowired public void setA(A a) { this.a = a; } @Autowired public void setB(B a) { this.b = b; } } public class CFactory { private AutowireInjector autowireInjector; public C creaetC() { C c = new C(); //spring 会自动注入依赖 a b this.autowireInjector.autowire(c); return c; } @Autowired public void setAutowireInjector(AutowireInjector autowireInjector) { this.autowireInjector = autowireInjector; } }
这样不论C的依赖要求如何变化,CFactory里面都只要注入autowireInjector就行了。改了C不需要动CFactory。
利用AOP简化依赖注入
尽管有了AutowireInjector,但是还要注入很多AutowireInjector,手动调用autowire方法,还是不够方便。假如限定Entity只能通过Factory或Repository获取,我们就可以使用AOP,对Factory和Repository返回的领域对象注入依赖。用如下代码实现:@Component @Aspect public class AutoWireAopConfig { private AutowireInjector autowireInjector; @Pointcut("execution(public * com.my..*Factory.create*(..))") public void factoryCreate() { } ; @Pointcut("execution(public * com.my..*Repository.find*(..))") public void repositoryFind() { } ; @AfterReturning(pointcut = "factoryCreate() || repositoryFind()", returning = "returnObject") public void injectAutowire(Object returnObject) { doInjection(returnObject); } public void doInjection(Object o) { if (o == null) { return; } if (o instance 7fe8 of Collection) { Collection c = (Collection) o; for (Object subObject : c) { doInjection(subObject); } return; } if (o.getClass().isArray()) { int length = Array.getLength(o); for (int i = 0; i < length; i++) { doInjection(Array.get(o, i)); } return; } if (o instanceof Map) { Collection c = ((Map) o).values(); for (Object subObject : c) { doInjection(subObject); } return; } if (o.getClass().getCanonicalName().startsWith("com.my")) { this.autowireInjector.autowire(o); } } @Autowired public void setAutowireInjector(AutowireInjector autowireInjector) { this.autowireInjector = autowireInjector; } }
这样,只要Factory和Repository以Factory和Repository作为类名的后缀,以create find作为方法的前缀,其返回值就会被注入依赖,而且支持返回领域对象集合。那此不通过Factory和Repository创建的对象,还是须要手动的注入依赖。
给hibernate载入的对象注入依赖
如果对象是通过hibernate从数据库载入的,那么可以通过hibernate的EntityListener注入依赖。首先得定义Listener类:public class HibernateEntityDependencyInjector implements PostLoadEventListener, MergeEventListener { private AutowireInjector autowireInjector; @Override public void onPostLoad(PostLoadEvent event) { this.injectDependency(event.getEntity()); } @Override public void onMerge(MergeEvent event) throws HibernateException { this.injectDependency(event.getEntity()); } @Override public void onMerge(MergeEvent event, Map copiedAlready) throws HibernateException { this.injectDependency(event.getEntity()); } protected void injectDependency(Object obj) { if (obj != null) { this.autowireInjector.autowire(obj); } } @Autowired public void setAutowireInjector(AutowireInjector autowireInjector) { this.autowireInjector = autowireInjector; } }
然后通过spring,把它配置到SessionFactory里面:
<bean id="hibernateEntityDependencyInjector" class="com.my.HibernateEntityDependencyInjector"/> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="configLocation" value="classpath:/hibernate.cfg.xml"/> <property name="eventListeners"> <map> <entry key="post-load" value-ref="hibernateEntityDependencyInjector"/> <entry key="merge" value-ref="hibernateEntityDependencyInjector"/> </map> </property> </bean>
这样,在post-load和merge的时候,会注入依赖。对于@Embedded的对象,这样是不管用的,还没有找到更好的办法。
相关文章推荐
- Spring中利用AOP对领域对象(非依赖注入的对象,如new操作符、反射的方式生存的对象)下面是spring配置文件的一部分 <context:load-time-weaver /> <be
- Spring.NET依赖注入框架学习-- 泛型对象的创建和使用
- 85——Spring中对象依赖注入,给对象属性赋值,包含哪些内容(1条)
- 使用dom4j:读取spring配置文件,实例化bean对象并注入依赖对象
- Spring.NET依赖注入框架学习--简单对象注入
- 模拟spring注入依赖对象
- spring 之脱离容器管理创建的对象进行依赖注入
- spring 依赖对象的注入方式(3种) 和 公共属性的设置abstract="true" parent
- SpringIOC容器创建对象及依赖注入的几种方式
- Spring注入依赖对象
- Spring给普通对象注入依赖
- Spring之对象依赖关系(依赖注入Dependency Injection)
- Spring整理系列(02)——spring依赖注入,组装对象之间的依赖关系
- spring 依赖注入到直接new 对象
- Spring.NET教程(六)——依赖对象的注入(基础篇)
- spring基于xml文件注入依赖对象
- Junit和spring整合,使用Spring托管对象进行依赖注入,方便测试
- (5) 编码剖析Spring装配基本属性的原理【附加:注入依赖对象的两种方式】
- (4) 编码剖析Spring装配基本属性的原理【附加:注入依赖对象的两种方式】
- Spring依赖注入之对象注入