知识点
相关文章
更多最近更新
更多Spring4新特性——核心容器的其他改进
2019-03-19 08:54|来源: 开涛
1、Map依赖注入:
@Autowired
private Map<String, BaseService> map;
这样会注入:key是bean名字;value就是所有实现了BaseService的Bean,假设使用上一篇的例子,则会得到:
{organizationService=com.sishuok.spring4.service.OrganizationService@617029, userService=com.sishuok.spring4.service.UserService@10ac73b}
2、List/数组注入:
@Autowired
private List<BaseService> list;
这样会注入所有实现了BaseService的Bean;但是顺序是不确定的,如果我们想要按照某个顺序获取;在Spring4中可以使用@Order或实现Ordered接口来实现,如:
@Order(value = 1)
@Service
public class UserService extends BaseService<User> {
}
这种方式在一些需要多态的场景下是非常有用的。
3、@Lazy可以延迟依赖注入:
@Lazy
@Service
public class UserService extends BaseService<User> {
}
@Lazy
@Autowired
private UserService userService;
我们可以把@Lazy放在@Autowired之上,即依赖注入也是延迟的;当我们调用userService时才会注入。即延迟依赖注入到使用时。同样适用于@Bean。
4、@Conditional
@Conditional类似于@Profile(一般用于如我们有开发环境、测试环境、正式机环境,为了方便切换不同的环境可以使用
@Profile指定各个环境的配置,然后通过某个配置来开启某一个环境,方便切换)
,但是@Conditional的优点是允许自己定义规则。可以指定在如@Component、@Bean、@Configuration等注解的类上,以绝对Bean是否创建等。首先来看看使用@Profile的用例,假设我们有个用户模块:
1、在测试/开发期间调用本机的模拟接口方便开发;
2、在部署到正式机时换成调用远程接口;
public abstract class UserService extends BaseService<User> {
}
@Profile("local")
@Service
public class LocalUserService extends UserService {
}
@Profile("remote")
@Service
public class RemoteUserService extends UserService {
}
我们在写测试用例时,可以指定我们使用哪个Profile:
@ActiveProfiles("remote")
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring-config.xml")
public class ServiceTest {
@Autowired
private UserService userService;
}
这种方式非常简单。如果想自定义如@Profile之类的注解等,那么@Conditional就派上用场了;假设我们系统中有好多本地/远程接口,那么我们定义两个注解@Local和@Remote注解要比使用@Profile方便的多;如:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Conditional(CustomCondition.class)
public @interface Local {
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Conditional(CustomCondition.class)
public @interface Remote {
}
public class CustomCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
boolean isLocalBean = metadata.isAnnotated("com.sishuok.spring4.annotation.Local");
boolean isRemoteBean = metadata.isAnnotated("com.sishuok.spring4.annotation.Remote");
//如果bean没有注解@Local或@Remote,返回true,表示创建Bean
if(!isLocalBean && !isRemoteBean) {
return true;
}
boolean isLocalProfile = context.getEnvironment().acceptsProfiles("local");
//如果profile=local 且 bean注解了@Local,则返回true 表示创建bean;
if(isLocalProfile) {
return isLocalBean;
}
//否则默认返回注解了@Remote或没有注解@Remote的Bean
return isRemoteBean;
}
}
然后我们使用这两个注解分别注解我们的Service:
@Local
@Service
public class LocalUserService extends UserService {
}
@Remote
@Service
public class RemoteUserService extends UserService {
}
首先在@Local和@Remote注解上使用@Conditional(CustomCondition.class)指定条件,然后使用@Local和@Remote注解我们的Service,这样当加载Service时,会先执行条件然后判断是否加载为Bean。@Profile就是这样实现的,其Condition是:org.springframework.context.annotation.ProfileCondition。可以去看下源码,很简单。
5、基于CGLIB的类代理不再要求类必须有空参构造器了:
这是一个很好的特性,使用构造器注入有很多好处,比如可以只在创建Bean时注入依赖,然后就不变了,如果使用setter注入,是允许别人改的。当然我们可以使用spring的字段级别注入。如果大家使用过如Shiro,我们可能要对Controller加代理。如果是类级别代理,此时要求Controller必须有空参构造器,有时候挺烦人的。spring如何实现的呢?其借鉴了objenesis类库的思想,可以去其官网看看介绍。这样就支持如下方式的构造器注入了:
@Controller
public class UserController {
private UserService userService;
@Autowired
public UserController(UserService userService) {
this.userService = userService;
}
}
org.springframework.cglib.proxy.Enhancer在其github和maven仓库中的source中竟然木有,其github:https://github.com/spring-projects/spring-framework/tree/master/spring-core/src/main/java/org/springframework/cglib;难道忘了吗?
转在:http://jinnianshilongnian.iteye.com/blog/1989379
相关问答
更多-
国内正儿八经的Spring4学习视频_谁与争锋_有且只有尚硅谷[2022-03-14]
谢谢楼主,共同发展 -
国内正儿八经的Spring4学习视频_谁与争锋_有且只有尚硅谷[2022-01-15]
谢谢楼主,共同发展 查看更多答案>> -
java1.6新特性[2022-03-29]
1.Desktop类和SystemTray类 前者可以用来打开系统默认浏览器浏览指定的URL,打开系统默认邮件客户端给指定的邮箱发邮件,用默认应用程序打开或编辑文件(比如,用记事本打开以txt为后缀名的文件), 用系统默认的打印机打印文档;后者可以用来在系统托盘区创建一个托盘程序。 2.使用JAXB2来实现对象与XML之间的映射 JAXB是Java Architecture for XML Binding的缩写,可以将一个Java对象转变成为XML格式,反之亦然。 我们把对象与关系数据库之 ... -
是不是有一款什么手机软件,可以很自然的拉长腿部?不是美图秀秀,有知道的不?[2022-10-20]
spring -
spring4的jar包的问题[2022-03-06]
xxxx-source.jar是xxxx.jar的源码,你要看xxxx.jar中的类的实现就要导入xxxx-source.jar,xxxx-docs.jar是xxxx.jar的说明api,可以通过javadocs导入查看说明,spring-build-src.jar就是一般的jar包,你可以看到里面是.class文件,不是源码,没用过不知道干嘛的 -
myeclipse怎么添加spring4 支持啊?[2022-03-01]
在网上搜了很多关于4.x的头文件的配置可是没有一个说的,没办法后来想到了spring-framework-reference.doc 解压打开运行beans.xml里面就有现成的,直接copy过来就可以了; 注意里面有很多不好分辨的,所以你需要下载的是类似下面的:spring-framework-4.0.0.RELEASE-dist.zip 在下载的同时,最好将该版本以.doc结尾的也下下来,因为这个是spring的开发文档 -
国内正儿八经的Spring4学习视频_谁与争锋_有且只有尚硅谷[2022-09-12]
谢谢楼主,共同发展 查看更多答案>> -
春天的英语怎么读?[2022-05-21]
spring -
系统核心为新特性是什么意思?[2022-12-29]
我理解可以通过新特性区分核心版本和新旧版本 -
您调用entityManagerFactoryBean.setDataSource(dataSource())的事实应该意味着您不需要调用jpaProperties.put(PROPERTY_NAME_H_CONNECTION_PROVIDER, env.getRequiredProperty(PROPERTY_NAME_H_CONNECTION_PROVIDER)) 。 您正在混合两种初始化样式。 源自以下的堆栈跟踪: com.zaxxer.hikari.hibernate.HikariConnectio ...