Spring学习(一)——容器注入

开篇先小小感慨一下:人生全都是命运的安排呀,读大学、研究生躲了这么多年的Java,最终都要还回来啊。今天开始学习Spring了,开始搬砖的人生

Spring基础

为了降低Java开发的复杂性,Spring采用了以下4种关键策略:

1、基于POJO的轻量级和最小侵入性编程,所有东西都是bean;

2、通过IOC,依赖注入(DI)和面向接口实现松耦合;
IOC(Inversion of controll 控制反转):对象之间的依赖关系由容器来控制。
DI(Dependency injection 依赖注入):容器通过调用对象提供的set方法或者构造器来建立依赖关系。
IOC是目标,DI是实现手段。
3、基于切面(AOP)和惯例进行声明式编程;

4、通过切面和模版减少样式代码,RedisTemplate,xxxTemplate;

1. set方式注入(较常用)

被注入类提供set方法,配置元素
以下给出一个简单的set方式注入依赖关系的例子:
1、配置xml文件

<bean id="b1" class="com.niuchen.spring.ioc.B"/>
 <!--
     property表示实用set方法注入依赖关系。
     其中,name指定属性名(注入类的对象属性),ref指定属性值(注入的bean的id)
-->
<bean id="a1" class="com.niuchen.spring.ioc.A">
    <property name="b" ref="b1"/>
</bean>

2、定义类

// 注入类
public class B {
    public B(){
        System.out.println("B");
    }

    public void f1(){
        System.out.println("B's f1");
    }
}

// 被注入类
public class A {
    private B b;//实际应用中更多使用接口定义对象属性,防止代码的修改,此处只为示例
    public A(){
        System.out.println("A");
    }
	// B类的set方法,注意方法名不可随意定义
    public void setB(B b) {
        System.out.println("setB");
        this.b = b;
    }

    public void excute(){
        System.out.println("excute");
        // 注入依赖后在A类中直接调用B类方法
        b.f1();
    }
}


3、测试例

public class TestCase {
    @Test
    public void test3(){
        AbstractApplicationContext ac = new ClassPathXmlApplicationContext("ioc.xml");
        A a = ac.getBean("a1", A.class);
        a.excute();
    }
2. 构造器方式注入

1.添加相应构造器

public class A {
    //接口类型多态,避免了代码的修改
    private IB b;
    public A(){
        System.out.println("A");
    }
	// 添加相应的构造器
    public A(IB b){
        System.out.println("A(B)");
        this.b = b;
    }

    public void excute(){
        System.out.println("excute");
        b.f1();
    }
}

2.配置constructor-arg元素

<bean id="b2" class="com.niuchen.spring.ioc2.B"/>
<!--  constructor-arg 配置构造器注入
    index指定参数下标
  -->
<bean id="a2" class="com.niuchen.spring.ioc2.A">
    <constructor-arg index="0" ref="b2"/>
</bean>
3. 自动装配

spring容器根据某种规则自动建立对象之间的依赖关系。

  • 默认情况下,容器不会自动装配。
  • 可以通过指定autwire属性告诉容器进行自动装配(容器底层仍然通过上文的方式建立依赖关系)。
public class Waiter {
    public Waiter(){
        System.out.println("Waiter");
    }
}
public class Restaurant {
    private Waiter wt;
    public Restaurant(){
        System.out.println("Restaurant");
    }

    public void setWt(Waiter wt) {
        System.out.println("setwt");
        this.wt = wt;
    }

    @Override
    public String toString() {
        return "Restaurant{" +
                "wt=" + wt +
                '}';
    }
}

配置xml

<bean id="wt" class="com.niuchen.spring.autoIn.Waiter"/>
    <!--  autowire:自动装配
        byName:容器根据属性名查找对应id的bean,并调用相应set方法注入。
               如果没有对应属性名的bean,则注入空值。
        byType:容器根据属性类型查找对应类型class的bean,并调用相应set方法注入。
               如果没有对应属性名的bean,则注入空值。
               如果有多个符合条件的bean则保报错。
        constructor:容器根据属性类型查找对应类型class的bean,并调用相应构造器方法注入。
      -->
    <bean id="rest" class="com.niuchen.spring.autoIn.Restaurant" autowire="byName"/>

junit测试

	@Test
    // 自动装配
    public void test5(){
        AbstractApplicationContext ac = new ClassPathXmlApplicationContext("auto.xml");
        Restaurant rest = ac.getBean("rest", Restaurant.class);
        System.out.println(rest);

    }
    /**
    *测试结果:Waiter
	*		  Restaurant
	*		  setwt
	*		  Restaurant{wt=com.niuchen.spring.autoIn.Waiter@eafc191}
    **/
4. 注入基本类型值

配置property属性的value标签。

public class ValueBean {
    private String name;
    private int age;
	
    public ValueBean(){System.out.println("Value");}
    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "ValueBean{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

<bean id="vb" class="com.niuchen.spring.value.ValueBean">
    <property name="name" value="哈哈哈"/>
    <property name="age" value="30"/>
</bean>
5. 注入集合类型值

set方式注入
与基本类型相似,只是配置文件不同,不同类型集合使用对应类型标签赋值,如List使用list标签,Set使用set标签。

<bean id="vb" class="com.niuchen.spring.value.ValueBean">
    <property name="name" value="哈哈哈"/>
    <property name="age" value="30"/>
    <property name="city">
         <list>
             <value>北京</value>
             <value>重庆</value>
             <value>上海</value>
         </list>
     </property>
     <property name="interest">
          <set>
              <value>台球</value>
              <value>吉他</value>
              <value>音乐</value>
          </set>
      </property>
      <property name="score">
           <map>
               <entry key="英语" value="60" />
               <entry key="数学" value="66"/>
           </map>
      </property>
      <property name="db">
          <props>
              <prop key="usearname">nc</prop>
              <prop key="password">123456</prop>
          </props>
      </property>
</bean>
public class ValueBean {
    private String name;
    private int age;
    private List<String> city;
    private Set<String> interest;
    private Map<String, Double> score;
    private Properties db;

    public ValueBean(){System.out.println("Value");}
    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setCity(List<String> city) {
        this.city = city;
    }

    public void setInterest(Set<String> interest) {
        this.interest = interest;
    }

    public void setScore(Map<String, Double> score) {
        this.score = score;
    }

    public void setDb(Properties db) {
        this.db = db;
    }

    @Override
    public String toString() {
        return "ValueBean{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", city=" + city +
                ", interest=" + interest +
                ", score=" + score +
                ", db=" + db +
                '}';
    }
}

引用注入集合类型的值
对上个例子以引用方式注入的配置方式,该方式配置更整洁灵活,方便集合值重用

    <!--  util命名空间  将集合类型的值配置成一个bean -->
    <util:list id="cityBean">
        <value>北京</value>
        <value>重庆</value>
        <value>上海</value>
    </util:list>
    <util:set id="interestBean">
        <value>台球</value>
        <value>吉他</value>
        <value>音乐</value>
    </util:set>
    <util:map id="scoreBean">
        <entry key="英语" value="60" />
        <entry key="数学" value="66"/>
    </util:map>
    <util:properties id="dbBean">
        <prop key="usearname">nc</prop>
        <prop key="password">123456</prop>
    </util:properties>
    <!--  引用的方式注入集合类型的值,方便重用  -->
    <bean id="vb2" class="com.niuchen.spring.value.ValueBean">
        <property name="city" ref="cityBean"/>
        <property name="interest" ref="interestBean"/>
        <property name="score" ref="scoreBean"/>
        <property name="db" ref="dbBean"/>
    </bean>

附加小知识点:
spring表达式:#{bean_id.属性}
Spring容器可以通过Spring表达式获取到其他bean的属性值。

<!--  spring表达式读取其他bean的属性  -->
    <bean id="sp1" class="com.niuchen.spring.value.SpelBean">
        <property name="name" value="#{vb.name}"/>
        <property name="city" value="#{vb.city[1]}"/>
        <property name="score" value="#{vb.score.english}"/>
        <property name="pageSize" value="#{config.pagesize}"/>
    </bean>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Growing_Snake

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值