Spring4(3)——IOC控制反转

1.Spring装配一个bean

在前一章中已涉及到此知识点,通俗的来讲:在建立People实体之后,在beans.xml 中配置,然后在实现类中调用 beans.xml文件,即装配完成,调用默认的构造方法。

  1. 建立实体 (People.java) 类

    public class People {
    
        private int id;
        private String name;
        private int age;
        
        // 构造方法
        public People() {     
            super();
        }
        
        public People(int id, String name, int age) {
            super();
            this.id = id;
            this.name = name;
            this.age = age;
        }  
    }  
  2. 配置beans.xml 文件

    <bean id="people" class="com.java1234.entity.People"></bean>
  3. 调用beans.xml 文件

    ApplicationContext ac=new ClassPathXmlApplicationContext("beans.xml");

2.依赖注入

  • 1. 属性注入;
  • 2. 构造函数注入;(通过类型;通过索引;联合使用)
  • 3. 工厂方法注入;(非静态工厂,静态工厂)
  • 4. 泛型依赖注入;(参考后面 Spring4 整合 Hibernate4 记录)
        <!-- 装配 -->
        <bean id="people" class="com.java1234.entity.People"></bean>
    
    
        <!-- 属性注入-->
        <bean id="people2" class="com.java1234.entity.People">
            <property name="id" value="1"></property>
            <property name="name" value="张三"></property>
            <property name="age" value="11"></property>
        </bean>

    <!-- 构造函数注入(通过类型)--> <bean id="people3" class="com.java1234.entity.People"> <constructor-arg type="int" value="2"></constructor-arg> <constructor-arg type="String" value="李四"></constructor-arg> <constructor-arg type="int" value="22"></constructor-arg> </bean> <!-- 构造函数注入(通过索引)--> <bean id="people4" class="com.java1234.entity.People"> <constructor-arg index="0" value="3"></constructor-arg> <constructor-arg index="1" value="王五"></constructor-arg> <constructor-arg index="2" value="55"></constructor-arg> </bean> <!-- 构造函数注入(类型索引联合使用)--> <bean id="people5" class="com.java1234.entity.People"> <constructor-arg index="0" type="int" value="4"></constructor-arg> <constructor-arg index="1" type="String" value="招六"></constructor-arg> <constructor-arg index="2" type="int" value="66"></constructor-arg> </bean>

    <!-- 工厂方法注入(非静态工厂)--> <bean id="peopleFactory" class="com.java1234.factory.PeopleFactory"></bean> <bean id="people6" factory-bean="peopleFactory" factory-method="createPeople"></bean> <!-- 工厂方法注入(静态工厂)--> <bean id="people7" class="com.java1234.factory.PeopleFactory2" factory-method="createPeople"></bean>
    public class Test2 {
    
        public static void main(String[] args) {
            ApplicationContext ac=new ClassPathXmlApplicationContext("beans.xml");
            People people=(People)ac.getBean("people");
            System.out.println(people);
            
            // 属性注入
            People people2=(People)ac.getBean("people2");
            System.out.println(people2);
            
            // 构造方法注入
            People people3=(People)ac.getBean("people3");
            System.out.println(people3);
            
            People people4=(People)ac.getBean("people4");
            System.out.println(people4);
            
            People people5=(People)ac.getBean("people5");
            System.out.println(people5);
            
            // 工厂方法注入
            People people6=(People)ac.getBean("people6");
            System.out.println(people6);
            
            People people7=(People)ac.getBean("people7");
            System.out.println(people7);
        }
    }

3.注入参数

  • 1. 基本类型值:参见上一节属性注入

  • 2. 注入 bean;

    <!-- 在 people2 里面注入 dog1 -->
    <bean id="dog1" class="com.java1234.entity.Dog">
      <property name="name" value="Jack"></property>
    </bean>
        
    <bean id="people2" class="com.java1234.entity.People">
        <property name="id" value="1"></property>
        <property name="name" value="张三"></property>
        <property name="age" value="11"></property>
        <property name="dog" ref="dog1"></property>  <!-- bean 注入 ,在 People.java 类中声明 dog类-->
    </bean>
  • 3. 内部 bean;

    <bean id="people3" class="com.java1234.entity.People">
        <property name="id" value="1"></property>
        <property name="name" value="张三"></property>
        <property name="age" value="11"></property>
        <property name="dog">
            <bean class="com.java1234.entity.Dog">
                <property name="name" value="Tom"></property>
            </bean>
        </property>
    </bean>
  • 4. null 值;

    <bean id="people4" class="com.java1234.entity.People">
         <property name="id" value="1"></property>
         <property name="name" value="张三"></property>
         <property name="age" value="11"></property>
         <property name="dog">
             <null></null>
         </property>
    </bean>
  • 5. 级联属性;

    <bean id="people5" class="com.java1234.entity.People">
        <property name="id" value="1"></property>
        <property name="name" value="张三"></property>
        <property name="age" value="11"></property>
        <property name="dog.name" value="Jack2"></property> 
    <!-- 因为此处用到了dog的属性,需要在声明的时候new一个dog对象。( private Dog dog = new Dog(); ) --> </bean>
  • 6. 集合类型属性;

    <bean id="people6" class="com.java1234.entity.People">
        <property name="id" value="1"></property>
        <property name="name" value="张三"></property>
        <property name="age" value="11"></property>
        <property name="dog" ref="dog1"></property>
        <property name="hobbies">
            <list>  <!-- list集合,可重复 -->
                <value>唱歌</value>
                <value>跳舞</value>
            </list>
        </property>
        <property name="loves">
            <set>  ·<!-- set集合,不可重复 -->
                <value>唱歌2</value>
                <value>跳舞2</value>
            </set>
        </property>
        <property name="works">
            <map>   <!-- Map键值对  -->
                <entry>
                    <key><value>上午</value></key>
                    <value>写代码</value>
                </entry>
                <entry>
                    <key><value>下午</value></key>
                    <value>测试代码</value>
                </entry>
            </map>
        </property>
        <property name="addresses">
            <props>   <!-- props 输入结果和Map类似,props 主要用于一些系统的配置-->
                <prop key="address1">aaaaa</prop>
                <prop key="address2">bbbbb</prop>
            </props>
        </property>
    </bean>
    private Dog dog;
    private List<String> hobbies=new ArrayList<String>();
    private Set<String> loves=new HashSet<String>();
    private Map<String,String> works=new HashMap<String,String>();
    private Properties addresses=new Properties();

4.自动装配

通过配置 default-autowire 属性(byName,byType,constructor),Spring IOC 容器可以自动为程序注入 bean;默认是 no,不启用自动装配;

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd"
        default-autowire="constructor"> <!-- 在此处设置 -->
  • byName:通过名称进行自动匹配,根据类中声明的属性名称选择注入的值;
    // People.java
    private Dog dog1;
    <!-- beans.xml -->
    <bean id="dog1" class="com.java1234.entity.Dog">
            <property name="name" value="Tom"></property>
    </bean>
    
    <bean id="dog2" class="com.java1234.entity.Dog">
        <property name="name" value="Jack"></property>
    </bean>
        
    <bean id="people1" class="com.java1234.entity.People">
        <property name="id" value="1"></property>
        <property name="name" value="张三"></property>
        <property name="age" value="11"></property>
    </bean>    
    // 测试
    public void test1() {
        private ApplicationContext ac=new ClassPathXmlApplicationContext("beans.xml");
        People people=(People)ac.getBean("people1");
        System.out.println(people);
    }    

    结果是:取出的狗名叫:Tom, 注意看People.java里面声明的狗是 dog1.

    .

  • byType:根据类型进行自动匹配,class="com.java1234.entity.Dog 
  • constructor:和 byType 类似,只不过它是根据构造方法注入而言的,根据类型,自动注入;

建议:自动装配机制慎用,它屏蔽了装配细节,容易产生潜在的错误;

5.方法注入

Spring bean 作用域默认是 单例 singleton; 可以通过配置 prototype ,实现多例; 方法注入 lookup-method .

  1. 默认单例 :每次获取的实例都是一样的
    System.out.println(ac.getBean("dog")=ac.getBean("dog")); //返回true
  2. 配置多例:每次获取的实例是不一样的 ( scope="prototype" 
    <bean id="dog" class="com.java1234.entity.Dog" scope="prototype">
        <property name="name" value="Jack"></property>
    </bean>
    System.out.println(ac.getBean("dog")=ac.getBean("dog")); //返回false

    注:当把dog bean作为属性注入给其他bean是,是同一条狗,而不是新的!所以可以使用lookup-method 方法注入修改

  3. bean注入时lookup-method
    <bean id="dog" class="com.java1234.entity.Dog" scope="prototype">
        <property name="name" value="Jack"></property>
    </bean>
        
    <bean id="people1" class="com.java1234.entity.People">
        <property name="id" value="1"></property>
        <property name="name" value="张三"></property>
        <property name="age" value="11"></property>
        <lookup-method name="getDog" bean="dog"/>  <!-- lookup-method -->
    </bean>

    注:此时要将getDog的方法改成抽象方法

    public abstract class People {
    
        private Dog dog;
        
        public abstract Dog getDog();
        
        public void setDog(Dog dog) {
            this.dog = dog;
        }   
    }

6.方法替换

假如,people1 有一条叫 Tom 的狗,people2 有一条叫 Jack 的狗,现在 people1 想要名叫 Jack 即 people2 的狗,即可用方法替换来实现。

此时需要将 people2 的 getDog() 方法替换成people1 的。

  • people2 实现接口 MethodReplacer
    public class People2 implements MethodReplacer {
    
        @Override
        public Object reimplement(Object arg0, Method arg1, Object[] arg2)
                throws Throwable {
            Dog dog=new Dog();
            dog.setName("Tom");
            return dog;
        }
    }
    <bean id="people2" class="com.java1234.entity.People2"></bean>
        
    <bean id="people1" class="com.java1234.entity.People">
        <property name="id" value="1"></property>
        <property name="name" value="张三"></property>
        <property name="age" value="11"></property>
        <replaced-method name="getDog" replacer="people2"></replaced-method>
        <!-- 用people2里面的reimplement来替换people1里面的getDog方法 -->
    </bean>

7.Bean之间的关系

  • 1. 继承:抽象的Bean可以定义一些公共的属性和方法( abstract="true"
    <!-- bstract="true" -->
    <bean id="abstractPeople" class="com.java1234.entity.People" abstract="true">
        <property name="className" value="高三5班"></property>
        <property name="age" value="19"></property>
    </bean>
        
    <!-- parent="abstractPeople" -->
    <bean id="lisi" parent="abstractPeople">  <!-- 无需class,可不建立实体类 -->
        <property name="id" value="2"></property>
        <property name="name" value="李四"></property>
        <property name="age" value="20"></property>  <!-- 属性可重写 -->
    </bean>
        
    <!-- 结果是:id=2——李四——高三5班——20岁 -->
  • 2. 依赖:未加入依赖的时候,按顺序执行bean;加入依赖后,会先去执行依赖的 bean ( depends-on="autority" ),可用于权限设置
    <!-- depends-on="autority" -->
    <bean id="zhangsan" parent="abstractPeople" depends-on="autority">
        <property name="id" value="1"></property>
        <property name="name" value="张三"></property>
    </bean>
    
    <bean id="autority" class="com.java1234.service.Authority"></bean>
  • 3. 引用:引用bean (ref),可参照前面的内容

8.Bean的作用范围

  • 1. singleton:Spring ioc 容器中仅有一个 Bean 实例,Bean 以单例的方式存在;
  • 2. prototype:每次从容器中调用 Bean 时,都返回一个新的实例;
  • 3. request: 每次 HTTP 请求都会创建一个新的 Bean;
  • 4. session: 同一个 HTTP Session 共享一个 Bean;
  • 5. global session: 同一个全局 Session 共享一个 Bean,一般用于 Portlet 应用环境;
  • 6. application: 同一个 Application 共享一个 Bean;
    <!-- scope="singleton/prototype/....." -->
    <bean id="dog" class="com.java1234.entity.Dog" scope="singleton">
        <property name="name" value="jack"></property>
    </bean>
        

 

 

 

猜你喜欢

转载自www.cnblogs.com/Cocoomg/p/9824417.html