Spring总结 1.装配bean

本随笔内容要点如下:

  • 依赖注入
  • Spring装配bean的方式
  • 条件化装配

一、依赖注入

  我理解的依赖注入是这样的:所谓的依赖,就是对象所依赖的其他对象。Spring提供了一个bean容器,它负责创建应用程序中的bean并通过依赖注入来协调这些对象之间的关系,实现自动创建与管理所创建的对象。我们只需要通过配置来命令Spring提供的容器来完成bean的装配。

二、Spring装配bean的方式

  在Spring中,装配bean有三种方式:

  1. 通过xml进行配置
  2. 通过Java进行配置
  3. 通过注解来自动扫描并配置

  先使用xml进行举例:

 1 package cn.powerfully.domain;
 2 
 3 public class ABean {
 4     private String str;
 5     private double num;
 6 
 7     public ABean() {
 8     }
 9 
10     public ABean(String str, double num) {
11         this.str = str;
12         this.num = num;
13     }
14 
15     public String getStr() {
16         return str;
17     }
18 
19     public void setStr(String str) {
20         this.str = str;
21     }
22 
23     public double getNum() {
24         return num;
25     }
26 
27     public void setNum(double num) {
28         this.num = num;
29     }
30 }

  在xml中配置如下

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4     xsi:schemaLocation="http://www.springframework.org/schema/beans
 5                         http://www.springframework.org/schema/beans/spring-beans.xsd">
 6 
 7 
 8     <bean id="aBean" class="cn.powerfully.domain.ABean">
 9         <constructor-arg name="str" value="bean"/>
10         <constructor-arg name="num" value="3.1415926"/>
11     </bean>
12 
13 </beans>

   使用bean标签来表示装载一个bean到Spring容器,默认该bean为单例,即容器中只有一个该类对象。对于字段的注入,上面使用了构造器注入,Spring还支持setter注入,通过<property>标签进行注入,具体的可以参考帮助文档。为了简化,spring提供了c命名空间和p命名空间,用来简化构造器注入和setter注入,上面的例子可以改编成如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:c="http://www.springframework.org/schema/c"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- <bean id="aBean" class="cn.powerfully.domain.ABean" p:str="p namespace" p:num="3.14" /> -->
    <bean id="aBean" class="cn.powerfully.domain.ABean" c:str="c namespace" c:num="3.14" />

</beans>

  其他基本类型和上面的例子一样,直接编写即可。对于注入对象与集合,将有所不同:

 1 package cn.powerfully.domain;
 2 
 3 import java.util.List;
 4 import java.util.Map;
 5 import java.util.Properties;
 6 
 7 public class BBean {
 8 
 9     private ABean aBean;
10     private List<String> list;
11     private Map<String, Integer> map;
12     private Properties props;
13     
14     public ABean getaBean() {
15         return aBean;
16     }
17 
18     public void setaBean(ABean aBean) {
19         this.aBean = aBean;
20     }
21 
22     public List<String> getList() {
23         return list;
24     }
25 
26     public void setList(List<String> list) {
27         this.list = list;
28     }
29 
30     public Map<String, Integer> getMap() {
31         return map;
32     }
33 
34     public void setMap(Map<String, Integer> map) {
35         this.map = map;
36     }
37 
38     public Properties getProps() {
39         return props;
40     }
41 
42     public void setProps(Properties props) {
43         this.props = props;
44     }
45 
46 }

  实例化该类时,需要注入对象、List、Map、Properties,xml配置如下:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4     xmlns:c="http://www.springframework.org/schema/c"
 5     xmlns:p="http://www.springframework.org/schema/p"
 6     xsi:schemaLocation="http://www.springframework.org/schema/beans
 7                         http://www.springframework.org/schema/beans/spring-beans.xsd">
 8 
 9     <!-- <bean id="aBean" class="cn.powerfully.domain.ABean" p:str="p namespace" p:num="3.14" /> -->
10     <bean id="aBean" class="cn.powerfully.domain.ABean" c:str="c namespace" c:num="3.14" />
11 
12     <bean id="bBean" class="cn.powerfully.domain.BBean" p:aBean-ref="aBean">
13         <!-- <property name="aBean" ref="aBean" /> -->
14         <property name="list">
15             <list>
16                 <value>item1</value>
17                 <value>item2</value>
18             </list>
19         </property>
20         <property name="map">
21             <map>
22                 <entry key="key1" value="1" />
23                 <entry key="key2" value="2" />
24             </map>
25         </property>
26         <property name="props">
27             <props>
28                 <prop key="key1">1</prop>
29                 <prop key="key2">2</prop>
30             </props>
31         </property>
32     </bean>
33 
34 </beans>

  如果想注入对象,则需要使用ref属性而不是value属性,ref属性值为bean对象的id。特别注意的是,如果使用p或c命名空间,其格式为c:propertyName-ref。常见的集合注入如上配置。关于具体的配置参见帮助文档,毕竟本随笔只是我的知识点简要回忆。

  接着是Java配置,个人觉得Java配置会比xml配置来得更爽,它具有很强的灵活性。还是使用上面的例子,配置如下:

 1 package cn.powerfully.config;
 2 
 3 import java.util.Arrays;
 4 
 5 import org.springframework.context.annotation.Bean;
 6 import org.springframework.context.annotation.Configuration;
 7 
 8 import cn.powerfully.domain.ABean;
 9 import cn.powerfully.domain.BBean;
10 
11 @Configuration
12 public class BeanConfig {
13 
14     @Bean
15     public ABean aBean() {
16         return new ABean("java configura", 3.1415);
17     }
18 
19     @Bean
20     public BBean bBean(ABean aBean) {
21         BBean bean = new BBean();
22         bean.setaBean(aBean);
23         bean.setList(Arrays.asList("item1", "item2"));
24         return bean;
25     }
26 
27 }

  通过注解@Configuration来表明该类是配置类,通过@Bean来表示该方法返回结果将放入容器,而方法返回结果即实例对象需要自己创建,其中在容器中bean的id为方法名。对于bBean,需要注入aBean对象,只需要在方法中填入参数,接着在代码里面直接引用即可。

   最后,回忆下注解。一般用到的注解为@Component与@Autowired。@Component标记在类上,表示该类需要被实例化并由Spring容器管理。@Autowired表示需要在Spring容器中查找符合的bean来设置到当前属性里,该注解可以用在字段、构造器、setter上。同时,还要开启自动扫描才能实现。

三、条件化装配

  有时,我们需要动态地来装配bean。当满足一定条件时我们才需要装配这个bean。Spring4之后,注解@Conditional可以实现这个功能。

1 @Conditional(UserCondition.class)
2 public class User {}
3 
4 public class UserCondition implements Condition {
5     @Override
6     public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
7         return false;
8     }
9 }

  当UserCondition中matches方法返回真时,才会创建User对象。关于该接口的具体使用请参考另一篇博文(还没写~.~)。

  其中@Profile是其中的一个特例,它也是使用@Conditonal来实现的。配置完该注解后,我们一开始可以通过设置profile类型来管理需要创建哪一系列bean。例如,在Web开发中,我们所选择的数据库可能根据运行时期的不同而不同。例如在开发环境,我们可能使用c3p0、dbcp等作为数据源。而在生产环境中,我们可能使用JNDI数据源。这是我们就可以使用profile了。我们先为不同的配置设置不同的profile,然后再使用时设置profile就行了。具体的还是参考另一篇博文。>_<

  简单例子如下:

  定义交通工具接口

1 package cn.powerfully.domain;
2 
3 public interface Vehicle {}

  定义车与飞机类并实现Vehicle接口:

 1 package cn.powerfully.domain;
 2 
 3 import org.springframework.context.annotation.Profile;
 4 import org.springframework.stereotype.Component;
 5 
 6 @Component
 7 @Profile("car")
 8 public class Car implements Vehicle {
 9     @Override
10     public String toString() {
11         return "Car";
12     }
13 }
 1 package cn.powerfully.domain;
 2 
 3 import org.springframework.context.annotation.Profile;
 4 import org.springframework.stereotype.Component;
 5 
 6 @Component
 7 @Profile("plane")
 8 public class Plane implements Vehicle {
 9     @Override
10     public String toString() {
11         return "Plane";
12     }
13 }

  创建配置类

1 package cn.powerfully.config;
2 
3 import org.springframework.context.annotation.ComponentScan;
4 import org.springframework.context.annotation.Configuration;
5 
6 @Configuration
7 @ComponentScan(basePackages = "cn.powerfully.domain")
8 public class VehicleConfig {}

  JUnit测试

 1 package cn.powerfully.test;
 2 
 3 import org.junit.Test;
 4 import org.junit.runner.RunWith;
 5 import org.springframework.beans.factory.annotation.Autowired;
 6 import org.springframework.test.context.ActiveProfiles;
 7 import org.springframework.test.context.ContextConfiguration;
 8 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 9 
10 import cn.powerfully.config.VehicleConfig;
11 import cn.powerfully.domain.Vehicle;
12 
13 @RunWith(SpringJUnit4ClassRunner.class)
14 @ContextConfiguration(classes=VehicleConfig.class)
15 @ActiveProfiles("car")
16 public class Demo {
17     @Autowired
18     private Vehicle vehicle;
19     
20     @Test
21     public void test(){
22         System.out.println(vehicle);
23     }
24 }

  当选用了car时,输出Car,选择plane时,输出了Plane...当然也可以使用xml配置:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:c="http://www.springframework.org/schema/c"
 4     xmlns:p="http://www.springframework.org/schema/p"
 5     xsi:schemaLocation="http://www.springframework.org/schema/beans
 6                         http://www.springframework.org/schema/beans/spring-beans.xsd">
 7 
 8     <beans profile="car">
 9         <bean id="vehicle" class="cn.powerfully.domain.Car" />
10     </beans>
11     
12     <beans profile="plane">
13         <bean id="vehicle" class="cn.powerfully.domain.Plane" />
14     </beans>
15 
16 
17 </beans>

  注意profile属性是位与beans标签上的。

posted @ 2017-01-18 21:43  兴趣使然~  阅读(244)  评论(0编辑  收藏  举报