上回说到,spring在没有xml的情况下 是如何运行起来的,这次 系统的说一下这种比xml更强大的配置bean方式 javaconfig
一、常用注解的的使用方式:
1、@ComponentScan :上次我在配置类上加上了这个注解,表明 spring会扫描其类所在包与其子包所有类。
默认是这样的,但是我也能指定需要扫描的包。
我在另一个包下new 了一个class SpringTestBean2
并在上面添加了@Component 注意这个类的包不要与配置类同包或其子包。
package per.hps.test2.bean;
import org.springframework.stereotype.Component;
@Component
public class SpringTestBean2 {
<span style="white-space:pre"> </span>
}
在测试类当中声明一个字段。 并且加上@Autowired
运行测试方法 发现报错:
无法注入该bean 也就是该bean找不到 因为@ComponentScan的范围搜不到这个类。
那在@ComponentScan注解上添加指定包。
@ComponentScan(basePackages={"per.hps"})
我将指定的包往上抬了一级。保证其包下和子包下都能扫到。、
这样就能扫到SpringTestBean2类了, 注意 这里的basePackages是负数形式,用数组是可以的。
其实还可以这样。
@Configuration
@ComponentScan(/*basePackages={"per.hps"}*/basePackageClasses=SpringTestBean2.class)
测试成功。
2、@Autowired自动装配
@Autowired可以添加在多个地方。 上面是放在了字段上。 也可以放在方法上。
或者构造器上。
public class SpringTest {
private SpringTestBean springTestBean;
@Autowired
public void setSpringTestBean(SpringTestBean springTestBean) {
this.springTestBean = springTestBean;
}
private SpringTestBean2 springTestBean2;
@Autowired
public SpringTest(SpringTestBean2 springTestBean2) {
super();
this.springTestBean2 = springTestBean2;
}
}
上面只截取了一部分。
可以看出 最简单的方式是直接加在字段上,最标准的方式是提供setget方法或者构造器上,我看着最别扭的方式是加载构造器上。
上面的代码在单元测试的时候会报错 原因是加了有参构造器。 目前尚未清楚原因,暂时搁置。
如果不是测试的话上面这个是没问题的。
如果说不确定某个bean是否被创建出来了。或者说这个bean有或者没有都可以。为了防止spring报错 该注解还提供了另一个功能
@Autowired(required = false)
当spring没有找到该bean时 不会报错。 默认是true 也就是必须的。
3、@Bean 声明bean
我之前提过配置类的概念。 就是专门创建一个配置类。负责bean的配置,不与逻辑代码耦合在一块。
@Bean 注解 就可以用在该类下
删除之前的创建bean的相关代码。
去除掉需要创建的bean的注解。
在配置类当中增加以下代码:
@Bean
public SpringTestBean getSpringTestBean(){
return new SpringTestBean();
}
该方法返回一个需要交给spring 管理的对象 然后打上@Bean注解。
这样 sping就会执行反射调用该方法 执行之后将该bean放到上下文(后面我就叫仓库了)中。
默认名字 不多说 原先解释过 该注解可以标识名字。在注解中加name。
javaconfig 强大的地方之一就是这! 这个方法是由我们自己代码写的 而且 返回的bean也不是写死的。 完全可以给他赋一个值。再return出去或者说我们可以随机return回对象出去。总之 bean 变的可控了。
@Bean 基于她的注入方式。 可以用形参方式注入进来。
比如:
@Bean(name="asd")
public SpringTestBean getSpringTestBean(SpringTestBean2 springTestBean2){
SpringTestBean bean = new SpringTestBean();
bean.setSpringTestBean2(springTestBean2);
return bean;
}
@Bean
public SpringTestBean2 getSpringTestBean2(){
return new SpringTestBean2();
}
还有 名字如果不一致也能注入进来。 spring 的注入是根据类型匹配的?这变我还真没注意过, 后续研究。
spring的注解有好多 先介绍这些。 后续还有,比如如何在javaconfig 中引用xml注解 如何在javaconfig中引入另一个javaconfig注解。
二、环境级别的条件装配(profile)。
spring提供了一种可以在不同环境下部署项目bean变化的一种方式。
意思就是说 当应用从开发环境 部署到QA环境时,一些配置可能需要变化。典型的就是数据源的配置, 当然 每个公司都有各自的做法。
举个例子:
先声明了一个bean org.springframework.beans.factory.config.PropertiesFactoryBean
注入locations 其中使用$取tomcat运行参数目录 然后去寻找对应的配置。
而下面接着配置
<context:property-placeholder> 标签 这个不多说 用来配置properties的。
这样每一个生产环境的服务器的运行参数不同 则 取到的properties文件也不同。
当找不到这个环境时。才会取项目目录里的配置文件。
这样有很多优点。具体不多说,重点不在这。
或者是:
利用maven的profiles 也是可以的, 在构建阶段 确定将哪一个配置编译到应用当中。
spring 也有提供了一种方式:
一个新的注解 @Profile 可以放在类上。 也可以放在方法上
必须指定一个name
代码:
@Configuration
@ComponentScan
@Profile("dev")
public class SpringConfigDemo {<pre name="code" class="java">}
也可以使用xml配置 在beans上。加profile属性
<beans ........各种namespace >
<beans profile="dev" >
<bean/>.,...各种bean
</beans>
<beans profile="test" >
<bean/>.,...各种bean
</beans>
</beans>
这样 表明了 该类或者该beans 下的一切配置 只有在profile为dev的时候才会生效。
也可以放到方法上。
放到方法上会更加灵活。这里不多写了。
激活一个profile 的方法有太多:
都与两个属性相关 spring.profiles.active和spring.profile.default
后者是默认的 前者是活动的 前者的优先级比后者高。若二者都不存在 则任何标注profile的类或者xml 都不会被激活。
1、作为DispatcherServlet的初始化参数。 这个类学过springmvc的话 肯定是知道的,这里还没到web 所以不介绍
2、作为web应用的上下文参数
3、作为JNDI条目 (不懂。)
4、作为环境变量 (这个6666)
5、作为哦jvm的系统属性
6、在集成测试类上 使用 @ActiveProfiles注解。
方法有很多 可以根据实际情况去使用 这里就不一一试了。 只试一个就行了。
上面我在配置类上加了profile注解 。
现在执行单元测试 是报错的。 用最后一种方式来指明profile
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfigDemo.class)
@ActiveProfiles("dev")
public class SpringTest {}
注意 这个注解里的profile 是复数形式。
也就是说可以同时激活多个profile。
其实这点也是可以想到的。
测试成功!!。
最后一个用注解的方式非常棒。以后单元测试啥的。 更加活性化。
总结:
灵活思考是一个程序员,不,是一个人最应该具备的习惯,发挥自己的想象力,让生活变的更有趣。
程序给我们带来的便利是无穷的 ,一块代码的好坏可以体现在其灵活性上。
spring提供的这种javaconfig配置bean方式以及profile 着实让我脑子不够用,并不是不理解,而是我一时想不出用一种非常非常好的方式去用。
肯定有一种特别妙的方式可以用。能让别人赞叹的非常66666的方式!!。