Spring 的 @Lookup 注解使用

最近工作中重构代码,需要将prototype类型的组件注入到singleton类型的组件中,但是只是声明scope是prototype,并使用@autowire注入的话,并不能满足需要。个人理解是项目启动的时候已经组装好了,导致单例bean中的原型bean也是同一个。

1. 介绍

我们来看一下如何通过方法级的@Lookup注解完成依赖注入。

2. 为什么用@Lookup?

一个有@Lookup注解的方法会告诉Spring,当我们调用这个方法时,Spring会返回一个方法返回值类型的实例。
实质上,Spring会父爱我们的注解方法并使用我们方法的返回值和参数作为BeanFactory#getBean方法的入参。
@Lookup注解的使用情景:

1) 向一个单例bean注入一个原型bean(prototype-scoped bean)(类似于Provider)
2) Injecting dependencies procedurally(暂译为程序依赖注入,有不妥请指正)
@Lookup相当于XML元素中的lookup-method

3. 如何使用@Lookup

3.1 向一个单例bean注入原型bean

当我们决定使用一个原型bean时,我们必须面对的问题就是我们的单例bean要如何使用这些原型bean呢?
当然可以使用Provider,但是@Lookup在某些方面更合适一些。
首先,我们先创建一个之后需要注入到单例bean的原型bean。

之后我们使用@Lookup创建一个单例bean:

使用@Lookup,我们能在单例bean中得到一个SchoolNotification实例。

注意,在StudentServices中,我们将getNotification方法设置成了一个空方法(we left the getNotification method as a stub)。
这是因为,spring通过调用beanFactory.getBean(StudentNotification.class)重写了这个方法,所以我们能将它置空。
3.2 部分就是说使用@Lookup注入的话,还可以通过构造器传参,其实就是spring调用beanFactory.getBean(class, name)实现的。

示例

下面看一个例子:




可以看到,使用@lookup时,两次的MyHandlerImpl不是同一个对象,而使用autowired注入的话,则是同一个对象。
需要注意的是,被@lookup注解的方法需要是public的哦!

 

0

Spring工程无法注入bean的地方如何获取bean

0

@ConditionalOnClass实现根据判断某个类是否在classpath中来动态创建bean

前言

假设我要配置一个TiEasyRocketProducer bean,但是测试环境下可能不一定有它的依赖类DefaultMQProducer.class,这个时候就可以根据@ConditionalOnClass和@Profile来动态创建bean。

代码

0

使用@ConfigurationProperties注解实现springboot里配置映射到Java类上

yml配置

映射类

启动类

使用

0

spring profile 与 maven profile 多环境管理

实际开发中一个项目至少对应开发、测试、生成三种环境,如何方便的管理多环境是今天的要讨论的主题

Spring Profile

Spring Profile 是 Spring 提供的多环境管理方案。

如图,每种环境都对应一个 properties 文件,然后在application.properties中配置一下要使用的环境

上面配置匹配的是 application-dev.properties,如果写的是test,则匹配 application-test.properties。也就是说,Spring Profile 对配置文件的命名有要求,必须是 application- 开头

除了配置环境外,一些不随环境而变化的配置也应该放到 application.properties中,application-.properties最好只存放与环境相关的配置项

以上就是 Spring Profile 给出的多环境管理方案。通过改变 spring.profiles.active的值来切换不同的环境。这种方法简单易懂,但有两个问题。

  1. 每次切换环境要手动修改 spring.profiles.active 的值
  2. 打包的时候,要手动删除其它环境的配置文件,不然其它环境的敏感信息就都打包进去了

为了解决这两个问题,我们需要 maven profile 的配合

maven profile

  maven 的 profile 可以让我们定义多套配置信息,并指定其激活条件,然后在不同的环境下使用不同的profile配置。   

profile 的定义位置

在maven中有两个地方可以配置 profile

  1. pom.xml中:这里面定义的 profile 作用范围是当前项目
  2. {user}/.m2/settings.xml中:这里面定义的 profile 作用范围是所有使用了该配置文件的项目

settings.xml中的 profile

不同的地方 profile 中能定义的信息也不相同

  • 由于settings.xml作用范围宽泛, profile 中只能定义一些公共信息,如下
  • id:该 profile 的唯一标识
  • activation:在哪些情况下激活 profile,这里面有多种策略可供选择,只要满足其中一个条件就激活
  • repositories:远程仓库

由于能配置的东西有限,一般都会将 maven profile 配置在pom.xml

pom.xml中 的profile

pom.xml中:profile 能定义的东西就非常多了,如下

当然我们的目的也不是把它配全,而是解决 Spring Profile 遗留下来的两个问题。

首先看第一个问题

问题1

“每次切换环境要手动修改spring.profiles.active的值”

这个问题就可以通过配置 profile 解决,在pom的根节点下添加

如上,定义了三套环境,其中id为dev的是默认环境,三套环境中定义了叫 env的“变量”

如果你用的是idea编辑器,添加好后,maven控件窗口应该会多出一个 Profiles,其中默认值就是上面配置的dev

最小化的 profiles 已经配置好了,通过勾选上图中的Profiles,就可以快速切换 maven的 profile 环境。

现在 maven profile 可以通过 勾选上图中的Profiles 快速切换环境

Spring Profile 还得通过 手动修改spring.profiles.active的值来切环境

现在的问题是怎样让 maven profile的环境与Spring Profile一一对应,达到切换maven profile环境时,Spring Profile环境也被切换了

还记得maven profile 中定义的 env “变量”吗,现在只需要把

改成

就将maven profile 与 Spring Profile 环境关联起来了

当maven profile 将 环境切换成 test 时,在pom中定义的id为test的profile环境将被激活,在该环境下env的值是test,maven插件会将 @env@ 替换为 test,这样Spring Profile的环境也随之发生了改变。从上面可以看出,自定义的”变量”env的值还不能乱写,要与Spring Profile的环境相对应。

总结

  • 第一步,在pom文件中配置 profiles
  • 第二步,在application.properties配置文件中添加 spring.profiles.active=@env@

问题2

打包的时候,要手动删除其它环境的配置文件,不然其它环境的敏感信息就都打包进去了

解决这个问题需要在pom根节点下中配置 build 信息

  • directory:资源文件所在目录
  • includes:需要包含的文件列表
  • excludes:需要排除的文件列表

如上,配置了两个 <resource>,第一个先排除了src/main/resources目录下所有 application 开头是配置文件,第二个在第一个的基础上添加了所需的配置文件。注意 application-${env}.yml,它是一个动态变化的值,随着当前环境的改变而改变,假如当前环境是 id叫 dev的 profile,那么env的值为 dev。

这样配置后,maven在build时,就会根据配置先排除掉指定的配置文件,然后根据当前环境添加所需要的配置文件。

0

使用spring自定义参数解析器和自定义注解实现可插拔的获取登陆用户信息

前言

Web系统里,调接口时,通常需要获取当前登陆系统的用户信息,实现方法有很多,常见的是在aop切面里拦截接口进行是否鉴权验证,然后获取当前用户信息。

本篇文章,主要介绍的是另一种方式,spring的自定义参数解析器HandlerMethodArgumentResolver,结合自定义注解实现。

使用HandlerMethodArgumentResolver可以灵活的给某个接口做统一的参数处理,废话不多说,以下是实现步骤。

一、定义一个注解

改注解是用于标记待处理的参数,这边就是我们的User。

二、自定义参数处理类SecurityUserMethodArgumentResolver

让它实现HandlerMethodArgumentResolver,需要根据自己的业务重写两个方法。

  1. supportsParameter:用于判定是否需要处理该参数分解,返回true为需要,并会去调用下面的方法resolveArgument。
  2. resolveArgument:真正用于处理参数分解的方法,返回的Object就是controller方法上的形参对象。

三、controller类里使用

0

Spring的版本GA、PRE、SNAPSHOT区别说明

GA:General Availability,正式发布的版本,官方推荐使用此版本。在国外都是用GA来说明release版本的

PRE: 预览版,内部测试版. 主要是给开发人员和测试人员测试和找BUG用的,不建议使用

SNAPSHOT: 快照版,可以稳定使用,且仍在继续改进版本

0

Eclipse里Spring MVC4+Spring 4+Mybatis3+junit4+Maven3.0 整合搭建

创建maven工程

点击Eclipse菜单栏File->New->Ohter->Maven->选择项目目录->next->选择项目类型

搜索web,创建项目->next

填写groupId和artifact Id->finish

项目配置

右击项目-new

创建如下几个文件

配置build path

分别修改输出路径为

  • src/main/resources对应target/classes
  • src/main/java对应target/classes
  • src/test/resources对应target/test-classes
  • src/test/java对应target/test-classes

设置JDK版本

设置部署程序集(Web Deployment Assembly)

把两个test目录去掉!!!

到此项目算是部署完成了。

spring mvc+spring+mybatis配置

pom.xml文件

web.xml

dispatcher-servlet.xml

applicationContext-bean.xml

mybaitis.xml

单元测试代码

0