注入域对象而不是基础结构组件

依赖注入是Java(以及许多其他编程语言)中广泛使用的软件设计模式,用于实现控制反转 。 它提高了可重用性,可测试性,可维护性,并有助于构建松耦合的组件。 如今,依赖注入是将Java对象连接在一起的事实上的标准。

诸如Spring或Guice之类的各种Java框架可以帮助实现依赖注入。 从Java EE 6开始,还有一个正式的Java EE API用于依赖关系注入: 上下文和依赖关系注入 (CDI)。

我们使用依赖注入来注入服务,存储库,与域相关的组件,资源或配置值。 但是,以我的经验,依赖注入也可以用来注入域对象,这常常被忽略。

一个典型的例子是在Java许多应用程序中获取当前登录用户的方式。 通常,我们最终会向登录用户询问某些组件或服务。

此代码看起来可能类似于以下代码片段:

public class SomeComponent {@Injectprivate AuthService authService;public void workWithUser() {User loggedInUser = authService.getLoggedInUser();// do something with loggedInUser}
}

此处,将AuthService实例注入SomeComponent。 SomeComponent的方法现在使用AuthService对象来获取已登录用户的实例。

但是,除了注入AuthService之外,我们还可以将登录用户直接注入SomeComponent中。

可能看起来像这样:

public class SomeComponent {@Inject@LoggedInUserprivate User loggedInUser;public void workWithUser() {// do something with loggedInUser}
}

在这里,User对象直接注入SomeComponent中,不需要AuthService实例。 如果存在多个类型为User的(托管)bean,则使用自定义批注@LoggedInUser来避免冲突。

Spring和CDI都可以进行这种类型的注入(并且配置实际上非常相似)。 在下一节中,我们将看到如何使用Spring注入域对象。 在此之后,我将描述使用CDI进行相同操作所需的更改。

使用Spring进行域对象注入

要注入上面示例中所示的域对象,我们只需要做两个小步骤。

首先,我们必须创建@LoggedInUser批注:

import java.lang.annotation.*;
import org.springframework.beans.factory.annotation.Qualifier;@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface LoggedInUser {}

请注意@Qualifier批注,它将@LoggedInUser变成自定义限定符。 如果有多个相同类型的bean可用,Spring会使用限定符来避免冲突。

接下来,我们必须在我们的Spring配置中添加一个bean定义。 我们在这里使用Spring的Java配置,也可以使用xml配置来完成。

@Configuration
public class Application {@Bean@LoggedInUser@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)public User getLoggedInUser() {// retrieve and return user object from server/database/session}
}

在getLoggedInUser()内部,我们必须检索并返回当前登录用户的实例(例如,通过从第一个代码片段中询问AuthService)。 使用@Scope,我们可以控制返回对象的范围。 最佳范围取决于域对象,并且在不同的域对象之间可能有所不同。 对于代表登录用户的User对象, 请求会话范围将是有效的选择。 通过用@LoggedInUser注释getLoggedInUser(),我们告诉Spring应该在每次注入用户类型为@LoggedInUser的bean时使用此bean定义。

现在,我们可以将登录用户注入其他组件:

@Component
public class SomeComponent {@Autowired@LoggedInUserprivate User loggedInUser;...
}

在这个简单的示例中,实际上不需要限定符注释。 只要只有一个类型为User的bean定义可用,Spring可以按类型注入已登录的用户。 但是,在注入域对象时,很容易发生您具有相同类型的多个bean定义。 因此,使用附加的限定符注释是一个好主意。 限定词凭借其描述性名称也可以充当文档(如果命名正确)。

简化Spring bean定义

注入许多域对象时,最终有可能在bean配置中一遍又一遍地重复作用域和代理配置。 在这种情况下,可以在自定义注释上使用Spring注释。 因此,我们可以简单地创建自己的@SessionScopedBean批注,以代替@Bean和@Scope:

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Bean
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public @interface SessionScopedBean {}

现在我们可以简化bean的定义:

@Configuration
public class Application {@LoggedInUser@SessionScopedBeanpublic User getLoggedInUser() {...}
}

Java EE和CDI

CDI的配置几乎相同。 唯一的区别是我们必须用javax.inject和CDI注释替换Spring注释。

因此,@LoggedInUser应该使用javax.inject.Qualifier进行注释,而不是org.springframework.beans.factory.annotation.Qualifier进行注释(请参阅: 使用Qualifiers )。

Spring bean定义可以用CDI Producer方法代替。 可以使用适当的CDI范围注释代替@Scope。

在注入点,可以将Spring的@Autowired替换为@Inject。

请注意,Spring还支持javax.inject注释。 如果将javax.inject依赖项添加到Spring项目中,则还可以使用@Inject和@ javax.inject.Qualifier。 这样做实际上是一个好主意,因为它可以减少Java代码中的Spring依赖关系。

结论

我们可以使用自定义注释和作用域bean将域对象注入到其他组件中。 注入域对象可以使您的代码更易于阅读,并且可以导致更清晰的依赖关系。 如果仅注入AuthService来获取登录用户,则实际上取决于登录用户而不是AuthService。

不利的一面是,它使您的代码更牢固地依赖于依赖注入框架,该框架必须为您管理bean范围。 如果要保持在Dependency Injection容器之外使用类的能力,则可能会遇到问题。

哪种类型的域对象适合注入在很大程度上取决于您正在处理的应用程序。 好的候选对象是您经常使用的领域对象,它不依赖于任何方法或请求参数。 当前登录的用户是可能通常适合注入的对象。

  • 您可以在GitHub上找到所示示例的源代码。

翻译自: https://www.javacodegeeks.com/2014/10/injecting-domain-objects-instead-of-infrastructure-components.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/362030.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

分享25个优秀的网站底部设计案例

相对于网站头部来说,关注网站底部设计的人很少。我们平常也能碰到有些网站的底部设计得很漂亮,给网站的呈现来一个完美的结尾。这篇文章收集了25个优秀的网站底部设计案例,一起欣赏。 me & oli La Bubbly Poogan’s Porch GiftRocket Lin…

wbepack中output.filename和output.chunkFilename

对于webpack配置中filename和chunkFilename在使用中有些不懂的地方,研究之后记录如下。 filename: string | function 此选项决定了每个输出 bundle 的名称。这些 bundle 将写入到 output.path 选项指定的目录下。 对于单个入口起点,filename 会是一个…

页面添加锚点后如何点击不改变URL?

直接奔主题&#xff0c;前端简单地锚点实现方法大家都会&#xff0c;无非就是在把 a 标签的 href 写成想要跳到的元素的id &#xff0c;比如点击 <a href"#box"></a> 页面就会自动滚动到 <div id"box"></div> 元素的位置。 那么这…

OP AMP - 反馈理论在运放中的应用

实际应用的系统绝大多数是闭环的&#xff0c;运放更是如此。 关于反馈理论&#xff0c;需要了解极点&#xff0c;零点&#xff0c;波特图&#xff0c;以及如何用相位裕度&#xff0c;幅值裕度 确定系统的稳定性&#xff0c;这里不作赘述 &#xff0c;不懂的部分可以到网上搜点…

具有Spring Boot和Java配置的Spring Batch教程

我一直在努力将Podcastpedia.org的一些批处理作业迁移到Spring Batch。 以前&#xff0c;这些工作是以我自己的方式开发的&#xff0c;我认为现在是时候使用一种更“标准化”的方法了。 因为我以前从未在Java配置中使用过Spring&#xff0c;所以我认为通过在Java中配置Spring B…

阅读react-redux源码 - 零

阅读react-redux源码 - 零阅读react-redux源码 - 一阅读react-redux源码(二) - createConnect、match函数的实现 react的技术栈一定会遇到redux&#xff0c;而在react中使用redux需要使用react-redux&#xff0c;那么react-redux是怎么包装redux已适用react的呢&#xff1f; …

kali linux 开启配置ssh服务

1. 一、配置SSH参数 修改sshd_config文件&#xff0c;命令为&#xff1a;vi /etc/ssh/sshd_config将#PasswordAuthentication no的注释去掉&#xff0c;并且将NO修改为YES //kali中默认是yes2. 将PermitRootLogin without-password修改为PermitRootLogin yes3. 然后&#xf…

CORS(跨域资源共享)

CORS&#xff08;跨域资源共享&#xff09;使用额外的HTTP头部来告诉浏览器&#xff0c;允许运行在origin(domain)上的Web应用访问来自不同源服务器上的指定资源。 浏览器访问一个web应用&#xff0c;这个web应用会发很多的跨域请求&#xff0c;例如加载不同源的JS/CSS脚本&am…

[转]jQuery设计思想

转自&#xff1a;http://kb.cnblogs.com/page/109875/ jQuery是目前使用最广泛的javascript函数库。 据统计&#xff0c;全世界排名前100万的网站&#xff0c;有46%使用jQuery&#xff0c;远远超过其他库。微软公司甚至把jQuery作为他们的官方库。 对于网页开发者来说&#xff…

Java转换难题者,不适合工作(或面试)

一个非常艰苦的面试问题可能是这样的&#xff1a; int i Integer.MAX_VALUE; i 0.0f; int j i; System.out.println(j Integer.MAX_VALUE); // true为什么打印出正确的文字&#xff1f; 乍一看&#xff0c;答案似乎很明显&#xff0c;直到您意识到如果长时间更改int&…

问题:jquery给标签添加事件,但标签还未加载会成功吗

之后研究解决转载于:https://www.cnblogs.com/sz-toosimple/p/11170912.html

Access-Ctrol-Allow-Headers:*兼容问题导致的跨域失败

现象&#xff1a; 通过抓包看到在部分客户端上跨域的非简单请求只发送一个预检的OPTIONS请求&#xff0c;之后的真实请求并没有发送。 出现问题的环境&#xff1a; 部分IOS低版本系统。 windows系统微信内必现&#xff08;2020-04-29&#xff09;。 分析 通过上面条件OPT…

在github上托管Maven存储库(包含源代码和javadoc)

如何通过maven将小型开源库提供给其他开发人员&#xff1f; 一种方法是将其部署在Maven Central Repository上 。 我想要做的是将其部署到github &#xff0c;因此我可以自由地对其进行修改。 这篇文章将告诉您如何做到这一点。 我将工件部署到github的典型方法是使用mvn depl…

关于移动端页面强制竖屏

最近工作中写了一个移动端的页面&#xff0c;本来是没什么的&#xff0c;但是有一个要求感觉很奇怪&#xff0c;从前也没有遇到过&#xff0c;就是我写的这个页面需要放在一个APP中&#xff0c;但是这个APP是横屏的&#xff0c;打开这个页面的webview也是横屏的&#xff08;最新…

敏捷开发绩效管理之四:为团队设立外部绩效目标(目标管理,外向型绩效)...

这是敏捷开发绩效管理的第四篇。&#xff08;之一&#xff0c;之二&#xff0c;之三&#xff0c;之四&#xff0c;之五&#xff0c;之六&#xff0c;之七&#xff09;最近在看德鲁克的书&#xff0c;发现其中很明确地写着“企业的绩效只存在于外部&#xff0c;而企业内部只有成…

面向对象程序设计-C++ Default constructor Copy constructor Destructor Operator Overloading【第九次上课笔记】...

先上笔记内容吧&#xff1a; 这次上课的内容有关 构造函数析构函数运算符重载return * this内容很细&#xff0c;大家好好回顾笔记再照应程序复习吧 :) #include <iostream>using namespace std;class Integer { public:int i;int geti () const {return this->i;}vo…

阅读react-redux源码 - 一

阅读react-redux源码 - 零阅读react-redux源码 - 一阅读react-redux源码(二) - createConnect、match函数的实现 阅读react-redux源码零中准备了一些react、redux和react-redux的基础知识。从使用的例子中可以看出来顶层的代码中需要用一个来自react-redux的Provider组件提供r…

【K8S in Action】服务:让客户端发现pod 并与之通信(2)

一 通过Ingress暴露服务 Ingress (名词&#xff09; 一一进入或进入的行为&#xff1b;进入的权利&#xff1b;进入的手段或地点&#xff1b;入口。一个重要的原因是每个 LoadBalancer 服务都需要自己的负载均衡器&#xff0c; 以及 独有的公有 IP 地址&#xff0c; 而 Ingres…

事件绑定on与hover事件

今天项目中UI设计了一个鼠标划入和划出的效果&#xff0c;本来这个小效果是非常简单的&#xff01;可是在实际的生产环境中就出现了一点点问题&#xff01;因为在实际的环境中&#xff0c;数据全部是用ajax异步加载进去的&#xff0c;这样就造成了hover方法不能用了。先看一下原…

Java EE + MongoDb与Apache TomEE和Jongo Starter项目

知道MongoDB和Java EE &#xff0c;但是您不知道如何将两者集成在一起&#xff1f; 您是否阅读了很多有关该主题的内容&#xff0c;但没有找到适合该目的的解决方案&#xff1f; 这个入门项目适合您&#xff1a; 您将学习如何以一种时尚的方式使用MongoDB和Java EE &#xff0…