用spring做领域对象的依赖注入

依赖注入是现在一个使用非常广泛的技术,极大的降低了编写程序的难度。对于领域层的代码,我们也想使用依赖注入。对于无状态的service repository factory等对象,我们可以用spring容器初始化它们,把它们作为普通的spring的bean,这样它们天生就能被注入依赖了。对于entity, value objects这些有状态的对象,依赖注入就有点麻烦了。

让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 instanceof 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的对象,这样是不管用的,还没有找到更好的办法。

转载于:https://my.oschina.net/komodo/blog/919176

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring中,可以使用领域驱动设计(Domain-Driven Design,简称DDD)模型来构建应用程序。以下是一些在Spring中实施DDD的常用技术和模式: 1. 领域模型(Domain Model):使用领域对象、实体、值对象和聚合根来表示业务领域中的概念和关系。可以使用Java类来表示这些领域模型。 2. 领域服务(Domain Service):在领域模型中,有些业务操作不适合归属于特定的实体或值对象,这时可以使用领域服务来处理这些操作。在Spring中,可以将领域服务实现为Spring的Service组件。 3. 聚合根(Aggregate Root):聚合根是领域模型中的一个重要概念,它是一组相关实体和值对象的根。聚合根负责维护聚合内部对象的一致性和完整性。在Spring中,可以使用注解(如`@Entity`、`@Component`)来标识聚合根类。 4. 仓储(Repository):仓储是用于持久化和检索领域对象的机制。在Spring中,可以使用Spring Data JPA或者自定义的数据访问层来实现仓储。 5. 应用服务(Application Service):应用服务用于协调领域模型和应用层之间的交互,处理应用层的请求,调用相应的领域服务和仓储。可以使用Spring的Service组件来实现应用服务。 6. 值对象(Value Object):值对象是不可变的,表示某个概念的属性或组合,没有唯一标识。在Spring中,可以将值对象实现为普通的Java类。 通过使用上述技术和模式,结合Spring框架的依赖注入、AOP等特性,可以更好地实现领域驱动设计,并构建具有高内聚、低耦合的Spring应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值