Spring框架的Ioc使用

文章目录


一、Spring是什么?

spring是一个开源的控制反转(Ioc)和面向切面(Aop)的容器框架
其优点:

(1)方便解耦,简化开发,实现软件各层之间的解耦

(2)方便集成各种优秀的框架,如:集成Hibernate、JPA、Struts2等,这样更便于应用的开发。

(3)降低javaEE的API的使用难度,容器提供的众多辅作类,使用这些类能够加快应用的开发,如: JdbcTemplate、 HibernateTemplate。

(4)方便程序的测试,容器提供单例模式支持,开发人员不再需要自己编写实现代码。

(5)AOP编程的测试,利用它很容易实现如权限拦截、运行期监控等功能。

(6)声明式事物的支持,可以使用容器提供的众多服务,如:事务管理服务、消息服务等等。当我们使用容器管理事务时,开发人员就不再需要手工控制事务,也不需处理复杂的事务传播

引入一个控制反转的实例进行解释

二、Spring的控制反转(Ioc)

1.什么是控制反转
(1) 定义:是应用本身不负责依赖对象的创建及维护,依赖对象的创建及维护是由外部容器负责的。这样控制权就由应用转移到了外部容器,控制权的转移就是所谓反转。
(2)引入一个控制反转的实例进行解释

比如我们写了一个接口,两个接口实现类,定义了一个服务类去处理使用接口中的两个实现类方法。在不改变原有代码的基础上,能够按照调用者自己的选择,去调用哪个接口的实现类,完全取决于调用者-----这就用到了依赖注入(DI)实现原理
代码如下(示例):
接口类

public interface StudentDao {
    public void delete();
}

两个接口实现类

public class StudentDaoImplMysql implements StudentDao{
    @Override
    public void delete() {
        System.out.println("使用mysql数据库删除数据");
    }
}
public class StudentDaoImplOracle implements StudentDao{
    @Override
    public void delete() {
        System.out.println("使用oracle数据库删除数据");
    }
}

业务处理服务类

public class StudentService {

    private StudentDao studentDao;

    public StudentService(StudentDao studentDao){
        this.studentDao = studentDao;
    }
    public void delete(){
        studentDao.delete();
    }
}

调用者测试类

public class Test {
    public static void main(String[] args) {
        StudentService service = new StudentService(new StudentDaoImplOracle());
        service.delete();
    }
}
2.什么是依赖注入
(1)定义:在运行期,由外部容器动态地将依赖对象注入到组件中(spring容器在创建被调用者的实例时,会自动将调用者需要的对象注入给调用者----调用者通过spring容器获得被调用者实例)
(2)springIoc依赖注入的两种方式:
  • 属性set方式注入
业务层接口类引入数据处理层类接口,并使用数据处理接口类中的实现类中的方法

业务层接口实现类中调用外部接口类关键代码

public class PersonServiceImpl implements PersonService {
 // 定义接口声明
   private PersonDao personDao;
    // 提供set()方法,用于依赖注入
   public void setPersonDao(PersonDao personDao) {
       this.personDao = personDao;
   }   // 实现PersonService接口的方法
   @Override
    public void addPerson() {
        personDao.add(); // 调用PersonDao中的add()方法
      System.out.println("addPerson()执行了...");
    }

 }

配置xml文件中的配置,被依赖者依赖被依赖者中,调用者中把被调用者引用属性进行连接,通过ref=""这个属性,而不是value=””这个属性建立依赖

<bean id="personService" class="com.mengma.ioc.PersonServiceImpl">
    <!-- 将personDao实例注入personService实例中 -->
    <property name="personDao" ref="personDao"/>
</bean>

  • 构造方法方式注入
    业务层接口实现类中调用外部接口类关键代码
public class PersonServiceImpl implements PersonService {
 // 定义接口声明
   private PersonDao personDao;
    // 提供set()方法,用于依赖注入
   public PersonServiceImpl(PersonDao personDao) {
       this.personDao = personDao;
   }   // 实现PersonService接口的方法
   @Override
    public void addPerson() {
        personDao.add(); // 调用PersonDao中的add()方法
      System.out.println("addPerson()执行了...");
    }

 }
3.springIoc容器的使用

(1)使用springIoc容器,这采用配置文件xml来进行对bean对象的创建和管理:applicationContext.xml文件就是spring容器,把需要该容器创建对象的类通过bean标签配置在此即可,默认是加载该文件时创建对象,每一个类只创建一个对象。
相关一些bean标签的属性以及属性值的简单介绍

  • id=“student” ,获取对象名称
  • class=“com.entor.entity.Student”,类名,容器会根据全类名路径字符串反射创建对象
  • lazy-init=“true”,延迟创建对象,在使用该对象时才创建并初始化,可缩短spring容器启动时间,节省内存空间
  • scope=“prototype”,每次调用都创建新的对象,默认是singleton单例
  • init-method=“init” ,对象初始化方法,只执行一次
  • destroy-method=“destroy”,对象销毁时调用的方法,只执行一次

(2)对于基本数据类型bean类,使用springIoc来管理

(一)主要是以在配置文件中的bean标签配置对象的创建和初始化
(1) Bean类代码
public class Bean {

    private Integer intValue;
    private String strValue;
    private String[] arrayValue;
    private List<String> listValue;
    private Set<String> setValue;
    private Map<String,String> mapValue;
    private Properties propValue;

    public Bean() {
    }

    public Bean(Integer intValue, String strValue, String[] arrayValue, List<String> listValue, Set<String> setValue, Map<String, String> mapValue, Properties propValue) {
        this.intValue = intValue;
        this.strValue = strValue;
        this.arrayValue = arrayValue;
        this.listValue = listValue;
        this.setValue = setValue;
        this.mapValue = mapValue;
        this.propValue = propValue;
    }

    public Integer getIntValue() {
        return intValue;
    }

    public void setIntValue(Integer intValue) {
        this.intValue = intValue;
    }

    public String getStrValue() {
        return strValue;
    }

    public void setStrValue(String strValue) {
        this.strValue = strValue;
    }

    public String[] getArrayValue() {
        return arrayValue;
    }

    public void setArrayValue(String[] arrayValue) {
        this.arrayValue = arrayValue;
    }

    public List<String> getListValue() {
        return listValue;
    }

    public void setListValue(List<String> listValue) {
        this.listValue = listValue;
    }

    public Set<String> getSetValue() {
        return setValue;
    }

    public void setSetValue(Set<String> setValue) {
        this.setValue = setValue;
    }

    public Map<String, String> getMapValue() {
        return mapValue;
    }

    public void setMapValue(Map<String, String> mapValue) {
        this.mapValue = mapValue;
    }

    public Properties getPropValue() {
        return propValue;
    }

    public void setPropValue(Properties propValue) {
        this.propValue = propValue;
    }

    @Override
    public String toString() {
        return "Bean{" +
                "intValue=" + intValue +
                ", strValue='" + strValue + '\'' +
                ", arrayValue=" + Arrays.toString(arrayValue) +
                ", listValue=" + listValue +
                ", setValue=" + setValue +
                ", mapValue=" + mapValue +
                ", propValue=" + propValue +
                '}';
    }
}

(2)配置文件进行对bean各属性赋值
<?xml version="1.0" encoding="UTF-8"?>
<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">
 <bean id="bean" class="com.entor.entity.Bean">
        <property name="intValue" value="1"/>
        <property name="strValue" value="张三"/>
        <property name="arrayValue">
            <array>
                <value>张三</value>
                <value>李四</value>
                <value>王五</value>
            </array>
        </property>
        <property name="listValue">
            <list>
                <value>张三</value>
                <value>李四</value>
                <value>王五</value>
            </list>
        </property>
        <property name="setValue">
            <set>
                <value>张三</value>
                <value>李四</value>
                <value>王五</value>
            </set>
        </property>
        <property name="mapValue">
            <map>
                <entry key="CN" value="中国"/>
                <entry key="EN" value="美国"/>
                <entry key="JP" value="日本"/>
            </map>
        </property>
        <property name="propValue">
            <props>
                <prop key="CN">中国</prop>
                <prop key="EN">美国</prop>
                <prop key="JP">日本</prop>
            </props>
        </property>
    </bean>
</beans>
(3)Student类对象代码
public class Student {
    private Integer id;
    private String name;
    private Integer age;

    public Student() {
        System.out.println("Student类对象创建");
    }

    public Student(Integer id, String name, Integer age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    public void init(){
        System.out.println("Student对象初始化");
    }
    public void destroy(){
        System.out.println("Student对象销毁");
    }
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

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

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

(4) 归纳xml对bean对象属性赋值
  • 基本数据类型直接赋值
<property name="intValue" value="1"/>
<property name="strValue" value="张三"/>
  • 数组类型赋值
 <property name="arrayValue">
            <array>
                <value>张三</value>
                <value>李四</value>
                <value>王五</value>
            </array>
</property>
  • list集合类型赋值
 <property name="listValue">
            <list>
                <value>张三</value>
                <value>李四</value>
                <value>王五</value>
            </list>
 </property>
  • set集合类型赋值
 <property name="setValue">
            <set>
                <value>张三</value>
                <value>李四</value>
                <value>王五</value>
            </set>
 </property>
  • map集合类型赋值
 <property name="mapValue">
            <map>
                <entry key="CN" value="中国"/>
                <entry key="EN" value="美国"/>
                <entry key="JP" value="日本"/>
            </map>
  </property>
  • 配置文件properties赋值
<property name="propValue">
            <props>
                <prop key="CN">中国</prop>
                <prop key="EN">美国</prop>
                <prop key="JP">日本</prop>
            </props>
</property>
(5)配置文件进行对Student类各属性赋值
<?xml version="1.0" encoding="UTF-8"?>
<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">
 <bean id="student"
          class="com.entor.entity.Student"
          lazy-init="true"
          scope="prototype"
          init-method="init"
          destroy-method="destroy">
        <property name="id" value="1"/>
        <property name="name" value="张三"/>
        <property name="age" value="20"/>
    </bean>
</beans>

(6)加载xml配置文件测试类
public class Test {
    public static void main(String[] args) {
        /*
        //用户自己创建对象
        Student s = new Student();
        s.setId(1);
        s.setName("张三");
        s.setAge(20);
        System.out.println(s);
        */
        //把对象创建的工作交给spring容器集中创建,要用的时候直接去spring容器中去拿
        //1、加载spring配置文件,启动spring容器,创建对象,每一个类默认单例模式创建,默认在加载文件时创建
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

        //2、从spring容器中获取对象
        Student student = (Student)context.getBean("student");
        Student s = context.getBean(Student.class);
        //3、使用对象
        System.out.println(student);
        System.out.println(s);
        System.out.println(s==student);
        //当true,当  scope="singleton"单例模式时;当false,当 scope="prototype",每次调用都创建新的对象

        Bean bean = (Bean) context.getBean("bean");
        System.out.println(bean);
        System.out.println("intValue:"+bean.getIntValue());
        System.out.println("strValue:"+bean.getStrValue());
        System.out.println("arrayValue:"+bean.getArrayValue());
        System.out.println("listValue:"+bean.getListValue());
        System.out.println("setValue:"+bean.getSetValue());
        System.out.println("mapValue:"+bean.getMapValue());
        System.out.println("propValue:"+bean.getPropValue());
    }
}

(二)主要是以注解形式实现bean对象的Ioc管理
需要在xml文件中添加自动扫描标签
  • 开启注解模式,这样就可以使用@ Resource 、@ PostConstruct、@ PreDestroy、@PersistenceContext、@Autowired、@Required等注解了,就可以实现自动注入
<context:annotation-config/>
  • 组件包扫描,指定包路径下的所有被注解@Component标识过的类,创建对象,除了具有context:annotation-config的功能之外,context:component-scan还可以在指定的package下扫描以及注册javabean
<context:component-scan base-package="com.entity"/>
  • 导入其他的配置文件,按照导入文件顺序加载,默认根据配置bean的先后顺序创建对象
 <import resource="applicationContext.xml"/>
  • 等同于上面的引入外部的xml文件,就是在加载配置文件路径时,其中applicationContext*.xml"中的*是改配置文件下的所有配置文件,但是不知道顺序,先后不确定
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext*.xml");

三、springIoc容器的依赖注入

对象之间的相互依赖注入

(1)xml配置实体类Bean1依赖于Bean2和Bean3实体类

  • set方法注入
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       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
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">
	<bean id="bean1" class="com.entity.Bean1">
        
        <property name="bean2" ref="bean2"/>
        <property name="bean3" ref="bean3"/>
        <!--对象之间引用关系要用ref修饰-->
	</bean>
</beans>
  • 构造方法注入
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       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
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">
	<bean id="bean1" class="com.entity.Bean1">
        
         <constructor-arg index="0" ref="bean2"/>
         <!--通过index位置指定构造方法参数传入的顺序,如果不指定,就是默认的按照参数传入顺序,不能错乱顺序-->
        <constructor-arg index="1" ref="bean3"/>
	</bean>
</beans>
  • Bean1关联的Bean2和Bean3的实体类
public class Bean1 {
    /**
     *  @Resource作用在属性上,默认根据属性名称去配置文件中查找对应的bean,
     * 创建对象后赋值给该属性变量,如果找不到,则根据属性类型去查找bean,
     * 如果再找不到或者有多个值报错
     *
     *  注解可以指定name属性,则根据指定的名称去配置文件查找,
     *  一旦指定了名称,则会根据指定的名称查找,如果找不到则报错
     *
     *     @Autowired:作用在属性上,默认根据属性类型去配置文件查找对应的bean,创建对象后赋值给该属性变量
     *     如果找不到或者找到多个,则根据属性名称去查找bean,如果找不到则会报错
     *  @Qualifier(value = "a")指定name属性名称查找bean,这个配合  @Autowired,如果找不到就会报错
     *
     *  总结:两个注解都是作用在属性上,set、get方法可省略
     */
   // @Resource/*指定ID属性值查找*/
    //@Autowired
    //@Qualifier(value = "bean2")
    private Bean2 bean2;
    /*@Resource*/
   // @Autowired
    private Bean3 bean3;

    public Bean1() {
    }

    public Bean2 getBean2() {
        return bean2;
    }

    public void setBean2(Bean2 bean2) {
        this.bean2 = bean2;
    }

    public Bean3 getBean3() {
        return bean3;
    }

    public void setBean3(Bean3 bean3) {
        this.bean3 = bean3;
    }

    public Bean1(Bean2 bean2, Bean3 bean3) {
        this.bean2 = bean2;
        this.bean3 = bean3;
    }

    @Override
    public String toString() {
        return "Bean1{" +
                "bean2=" + bean2 +
                ", bean3=" + bean3 +
                '}';
    }
}

//外部实体类
//@Component
public class Bean2 {
}

//@Component
public class Bean3 {
}

  • 测试类
public class Test1 {
    public static void main(String[] args) {
       // ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-bean.xml");
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-bean.xml");
        /*"applicationContext*.xml"中的*是改配置文件下的所有配置文件,但是不知道顺序,先后不确定*/
        /* ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext*.xml");
        * 与application配置文件中的  <import resource="applicationContext.xml"/>是一样的,但这个有先后顺序
        *
        * */
        Bean bean=context.getBean(Bean.class);
        Bean1 bean1=context.getBean(Bean1.class);
        //Bean2 bean2=context.getBean(Bean2.class);
        Bean2 bean22=(Bean2) context.getBean("bean2");

      /* Bean2 bean2=( Bean2 )context.getBean("bean2");*/
        // Bean2 bean22=( Bean2 )context.getBean("bean33");
        Bean2 bean2=context.getBean(Bean2.class);
        Bean3 bean3=context.getBean(Bean3.class);

       /* Bean3 bean3=(Bean3)context.getBean("bean33");*/
        System.out.println("bean = " + bean);
        System.out.println("bean1 = " + bean1);
        System.out.println("bean2 = " + bean2);
        System.out.println("bean22 = " + bean22);
      /*  System.out.println("bean22 = " + bean22);
        System.out.println(bean2==bean22);*/
        System.out.println("bean3 = " + bean3);

    }
}

(2)注解配置实体类Bean1依赖于Bean2和Bean3实体类

  • xml开启注解标签模式
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       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
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">
<!--组件包扫描,指定包路径下的所有被注解@Component标识过的类,创建对象,除了具有<context:annotation-config>的功能之外,<context:component-scan>还可以在指定的package下扫描以及注册javabean-->
    <context:component-scan base-package="com.entity"/>
    <!--开启注解模式--><!--这样就可以使用@ Resource 、@ PostConstruct、@ PreDestroy、@PersistenceContext、@Autowired、@Required等注解了,就可以实现自动注入-->
  <!--  <context:annotation-config/>-->
    <import resource="applicationContext.xml"/>
    <!--导入其他的配置文件,按照导入文件顺序加载,默认根据配置bean的先后顺序创建对象-->
</beans>
  • Bean1依赖Bean2和Bean3实体类
//Bean1实体类
@Component(value = "bean1")
public class Bean1 {
    /**
     *  @Resource作用在属性上,默认根据属性名称去配置文件中查找对应的bean,
     * 创建对象后赋值给该属性变量,如果找不到,则根据属性类型去查找bean,
     * 如果再找不到或者有多个值报错
     *
     *  注解可以指定name属性,则根据指定的名称去配置文件查找,
     *  一旦指定了名称,则会根据指定的名称查找,如果找不到则报错
     *
     *     @Autowired:作用在属性上,默认根据属性类型去配置文件查找对应的bean,创建对象后赋值给该属性变量
     *     如果找不到或者找到多个,则根据属性名称去查找bean,如果找不到则会报错
     *  @Qualifier(value = "a")指定name属性名称查找bean,这个配合  @Autowired,如果找不到就会报错
     *
     *  总结:两个注解都是作用在属性上,set、get方法可省略
     */
   // @Resource/*指定ID属性值查找*/
    @Autowired
    //@Qualifier(value = "bean2")
    private Bean2 bean2;
    /*@Resource*/
    @Autowired
    private Bean3 bean3;
    @Override
    public String toString() {
        return "Bean1{" +
                "bean2=" + bean2 +
                ", bean3=" + bean3 +
                '}';
    }
}
//Bean2实体类
@Component
public class Bean2 {
}
//Bean3实体类
@Component
public class Bean3 {
}
  • 测试类
public class Test1 {
    public static void main(String[] args) {
       // ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-bean.xml");
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-bean.xml");
        /*"applicationContext*.xml"中的*是改配置文件下的所有配置文件,但是不知道顺序,先后不确定*/
        /* ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext*.xml");
        * 与application配置文件中的  <import resource="applicationContext.xml"/>是一样的,但这个有先后顺序
        *
        * */
        Bean bean=context.getBean(Bean.class);
        Bean1 bean1=context.getBean(Bean1.class);
        //Bean2 bean2=context.getBean(Bean2.class);
        //Bean2 bean2=(Bean2) context.getBean("bean2");

      /* Bean2 bean2=( Bean2 )context.getBean("bean2");*/
        // Bean2 bean22=( Bean2 )context.getBean("bean33");
        Bean2 bean2=context.getBean(Bean2.class);
        Bean3 bean3=context.getBean(Bean3.class);

       /* Bean3 bean3=(Bean3)context.getBean("bean33");*/
        System.out.println("bean = " + bean);
        System.out.println("bean1 = " + bean1);
        System.out.println("bean2 = " + bean2);
      /*  System.out.println("bean22 = " + bean22);
        System.out.println(bean2==bean22);*/
        System.out.println("bean3 = " + bean3);

    }
}

springIoc容器获取bean对象两种方式

通过属性名称id来获取

  • xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       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
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">
	<bean id="bean2" class="com.entity.Bean2"/>
    <bean id="bean22" class="com.entity.Bean2"/>
    <bean id="bean3" class="com.entity.Bean3"/>
    <bean id="bean33" class="com.entity.Bean3"/>
</beans>
  • 测试类
public class Test1 {
    public static void main(String[] args) {
       // ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-bean.xml");
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-bean.xml");
        /*"applicationContext*.xml"中的*是改配置文件下的所有配置文件,但是不知道顺序,先后不确定*/
        /* ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext*.xml");
        * 与application配置文件中的  <import resource="applicationContext.xml"/>是一样的,但这个有先后顺序
        *
        * */
        Bean bean=context.getBean(Bean.class);
        Bean1 bean1=context.getBean(Bean1.class);
       // Bean1 bean11=(Bean1) context.getBean("bean1");
       // Bean2 bean2=context.getBean(Bean2.class);
        Bean2 bean22=(Bean2) context.getBean("bean22");

       Bean2 bean2=( Bean2 )context.getBean("bean2");
        // Bean2 bean22=( Bean2 )context.getBean("bean33");
       // Bean2 bean2=context.getBean(Bean2.class);
        //Bean3 bean3=context.getBean(Bean3.class);

       /* Bean3 bean3=(Bean3)context.getBean("bean33");*/
        System.out.println("bean = " + bean);
        System.out.println("bean1 = " + bean1);
       // System.out.println("bean11 = " + bean11);
        System.out.println("bean2 = " + bean2);
        System.out.println("bean22 = " + bean22);
      /*  System.out.println("bean22 = " + bean22);
        System.out.println(bean2==bean22);*/
       // System.out.println("bean3 = " + bean3);

    }
}

通过属性类型全限定类名获取

  • xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       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
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">
	<bean id="bean2" class="com.entity.Bean2"/>
    <bean id="bean22" class="com.entity.Bean2"/>
    <bean id="bean3" class="com.entity.Bean3"/>
    <bean id="bean33" class="com.entity.Bean3"/>
</beans>
  • 测试类------这时会报一个错误(No qualifying bean of type ‘com.entity.Bean2’ available: expected single matching bean but found 2: bean2,bean22),这就是getBean方法(运行时类名获取)限制,一旦定下bean的类型class,就是唯一性,不能存在另外一个同一个类型的bean
public class Test1 {
    public static void main(String[] args) {
       // ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-bean.xml");
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-bean.xml");
        /*"applicationContext*.xml"中的*是改配置文件下的所有配置文件,但是不知道顺序,先后不确定*/
        /* ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext*.xml");
        * 与application配置文件中的  <import resource="applicationContext.xml"/>是一样的,但这个有先后顺序
        *
        * */
        Bean bean=context.getBean(Bean.class);
        Bean1 bean1=context.getBean(Bean1.class);
       // Bean1 bean11=(Bean1) context.getBean("bean1");
        Bean2 bean2=context.getBean(Bean2.class);
        //Bean2 bean22=(Bean2) context.getBean("bean22");

      /* Bean2 bean2=( Bean2 )context.getBean("bean2");*/
        // Bean2 bean22=( Bean2 )context.getBean("bean33");
       // Bean2 bean2=context.getBean(Bean2.class);
        Bean3 bean3=context.getBean(Bean3.class);

       /* Bean3 bean3=(Bean3)context.getBean("bean33");*/
        System.out.println("bean = " + bean);
        System.out.println("bean1 = " + bean1);
       // System.out.println("bean11 = " + bean11);
        //System.out.println("bean2 = " + bean2);
       // System.out.println("bean22 = " + bean22);
      /*  System.out.println("bean22 = " + bean22);
        System.out.println(bean2==bean22);*/
        System.out.println("bean3 = " + bean3);
    }
}

xml配置文件中bean的id属性名称相同,属性类型不同,通过springIoc加载配置文件时会报错(Configuration problem: Bean name ‘bean33’ is already used in this element
Offending resource: class path resource [applicationContext-bean.xml]

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       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
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">

  <bean id="bean2" class="com.entity.Bean2"/>
    <bean id="bean33" class="com.entity.Bean2"/>
    <bean id="bean3" class="com.entity.Bean3"/>
    <bean id="bean33" class="com.entity.Bean3"/>
</beans>
xml配置文件注入集合对象(一对多的形式)
 <!--一个班级对象对应多个学生的集合类型的创建,给bean注入集合-->
    <bean id="classes" class="com.entity.Classes">
        <property name="classNo" value="1001"/>
        <property name="className" value="计本"/>
        <property name="students">
            <list>
                <ref bean="student1"/>
                <ref bean="student2"/>
            </list>
        </property>
    </bean>
    <bean id="student1" class="com.entity.Student">
        <property name="id" value="1"/>
        <property name="name" value="张三1"/>
        <property name="age" value="22"/>

    </bean>
    <bean id="student2" class="com.entity.Student">
        <property name="id" value="2"/>
        <property name="name" value="张三2"/>
        <property name="age" value="24"/>

    </bean>
scope作用域

spring管理的bean是根据scope来生成的,表示bean的作用域,共4中,默认是singleton(单例模式)

  • singleton:单例模式,表示通过Ioc容器获取的bean是唯一的
  • prototype:原型模式,表示通过Ioc容器获取的bean是不同的(不唯一)
  • request:请求,表示在一次http请求内有效
  • session:会话,表示在一个用户会话内有效
  • request和session只适用于Web项目,大多数情况下,使用的是单例和原型模式较多
  • prototype模式当业务代码获取Ioc容器中的bean时,spring才去调用无参构造创建对应的bean
  • singleton模式无论业务代码是否获取Ioc容器中的bean,spring在加载spring的xml配置文件时就会已经创建该bean了
spring对象之间的继承关系

这个是与java的单继承不同的是,java是类层面的继承关系,子类可以继承父类的内部结构信息;spring是对象层面的继承关系,子对象可以继承父对象的属性值
spring继承的关注点是在具体的对象,而不再具体的类,也就是不同的两个类的实例化对象可以完成继承,前提条件是子对象必须包含父对象的所有属性,同时可以在此基础上添加其他属性

  • 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<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">
    <!--所有类都创建,在xsi标签后面添加scope="prototype"-->
    <bean id="student" class="com.entity.Student" scope="singleton">
        <property name="id" value="2"/>
        <property name="name" value="张三2"/>
        <property name="age" value="22"/>

    </bean>
<!--    <bean id="stu" class="com.entity.Student" parent="student">-->
<!--        <property name="id" value="10"></property>-->
<!--        <property name="name" value="王五"/>-->
<!--        <property name="age" value="102"/>-->
<!--    </bean>-->
    <bean id="user" class="com.entity.User" parent="student">
        <property name="sex" value=""/>
    </bean>

</beans>
  • 实体类(User 类继承Student类)
@Data
public class Student {
    private Integer id;
    private String name;
    private Integer age;
}
@Data
public class User {
    private Integer id;
    private String name;
    private Integer age;
    private String sex;
}

  • 测试类
public class Test4 {
    public static void main(String[] args) {
       /* System.out.println("你好");这是用户自己创建对象
        Student s=new Student();
        s.setId(1);
        s.setName("张三");
        s.setAge(20);
        System.out.println("s = " + s);*/
        //把对象创建的工作交给spring容器集中创建,要用的时候直接去spring容器中去拿
        //1、加载spring配置文件,启动spring容器,创建对象,每一个类默认是单例模式创建对象
        //默认在加载文件时创建
       ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext1.xml");
       /*ClassPathXmlApplicationContext()---->src下的类路径*/
       //2、从spring容器中获取对象
        Student student = (Student)context.getBean("student");
        System.out.println("student="+student);
        //3、使用对象
        System.out.println("===========");
//        Student stu =(Student) context.getBean("stu");
//        System.out.println("stu = " + stu);
        User user =(User) context.getBean("user");
        System.out.println("user = " + user);
    }
}
springIoc容器的依赖bean属性(depends-on)

与继承关系类似的,依赖也是描述bean与bean之间的一种关系,配置依赖之后,被依赖的bean一定先创建,在创建依赖的bean。譬如A依赖于B,那么先创建B,然后再创建A(在没有引入depends-on这个属性时,在xml配置文件中按照bean标签的顺序依次创建bean,那么在加载获取bean对象顺序创建时,得到的对象顺序是按照xml配置文件顺序获取的,跟加载获取bean对象的顺序无关)

  • xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<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">
    <!--所有类都创建,在xsi标签后面添加scope="prototype"-->
    <bean id="classes" class="com.entity.Classes" depends-on="student">
        <property name="classNo" value="1"/>
        <property name="className" value="计本"/>
        <property name="students">
            <list>
                <ref bean="student"/>
<!--                <ref bean="student1"/>-->
            </list>
        </property>
    </bean>
    <bean id="student" class="com.entity.Student">
        <property name="id" value="1"/>
        <property name="name" value="王五"/>
        <property name="age" value="25"/>
    </bean>
</beans>
  • 实体类(Classes类依赖于Student类)
@Data
public class Classes {
    private Integer classNo;
    private String className;
    private List<Student> students;
    public Classes(){
        System.out.println("classes对象创建");
    }
}

@Data
public class Student {
    private Integer id;
    private String name;
    private Integer age;

    public Student() {
        System.out.println("Student类对象创建");
    }
}
  • 测试类
public class Test5 {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext2.xml");
        Classes classes =(Classes) context.getBean("classes");
        System.out.println("classes = " + classes);
        Student student =(Student) context.getBean("student");
        System.out.println("student = " + student);
//        Classes classes =(Classes) context.getBean("classes");
//        System.out.println("classes = " + classes);
    }
}
Spring的p命名空间

p的命名空间是对Ioc/DI的简化操作,使用怕p命名空间可以更加方便的完成bean的配置以及bean之间的依赖注入

  • xml配置文件
<?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:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--所有类都创建,在xsi标签后面添加scope="prototype"-->
    <bean id="classes" class="com.entity.Classes" p:classNo="1" p:className="数学" p:students-ref="student">

    </bean>
    <bean id="student" class="com.entity.Student" p:id="2" p:name="刘邦" p:age="20"/>
<!--    <bean id="classes" class="com.entity.Classes" depends-on="student">-->
<!--        <property name="classNo" value="1"/>-->
<!--        <property name="className" value="计本"/>-->
<!--        <property name="students">-->
<!--            <list>-->
<!--                <ref bean="student"/>-->
<!--&lt;!&ndash;                <ref bean="student1"/>&ndash;&gt;-->
<!--            </list>-->
<!--        </property>-->
<!--    </bean>-->
<!--    <bean id="student" class="com.entity.Student">-->
<!--        <property name="id" value="1"/>-->
<!--        <property name="name" value="王五"/>-->
<!--        <property name="age" value="25"/>-->
<!--    </bean>-->
</beans>
  • 实体类(Classes类依赖于Student类)
@Data
public class Student {
    private Integer id;
    private String name;
    private Integer age;

    public Student() {
        System.out.println("Student类对象创建");
    }
}

@Data
public class Classes {
    private Integer classNo;
    private String className;
    private List<Student> students;
    public Classes(){
        System.out.println("classes对象创建");
    }
}
  • 测试类
public class Test6 {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext3.xml");
        Classes classes =(Classes) context.getBean("classes");
        System.out.println("classes = " + classes);
        Student student =(Student) context.getBean("student");
        System.out.println("student = " + student);
//        Classes classes =(Classes) context.getBean("classes");
//        System.out.println("classes = " + classes);
    }
}

四、springIoc容器的工厂方法

Ioc通过工厂模式创建bean的两种方式

静态工厂方法
  • 实体类----工厂类(在此类中注入Car实体类)
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Car {
    private Integer id;
    private String name;
}


public class StaticFactory {
    private static Map<Integer, Car> map;
    static {
        map=new HashMap<>();
        map.put(1,new Car(1,"宝马"));
        map.put(2,new Car(2,"奔驰"));
    }
    public static Car getCar(Integer id){
        return map.get(id);
    }
}

  • xml配置文件
	<?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: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-->
   <bean id="car" class="com.cn.staticcarfactory.StaticFactory" factory-method="getCar">
       <constructor-arg value="1"/>
   </bean>
</beans>
  • 测试类
import com.entity.Car;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
    public static void main(String[] args) {
       ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-factory.xml");
        Car car = (Car)context.getBean("car");
        System.out.println("car = " + car);
    }
}
实例工厂方法
  • 实体类-----工厂类(在此类中注入Car实体类)
@Data
public class User {
    private Integer id;
    private String name;
    private Integer age;
    private String sex;
    private User(){

        System.out.println("User对象创建");
    }
}


public class InstanceFactory {
    private  Map<Integer, Car> map;
//    static {
//        map=new HashMap<>();
//        map.put(1,new Car(1,"宝马"));
//        map.put(2,new Car(2,"奔驰"));
//    }
    public InstanceFactory(){
        System.out.println("InstanceFactory对象创建");
        map=new HashMap<>();
        map.put(1,new Car(1,"比亚迪"));
        map.put(2,new Car(2,"红旗"));
    }
    public Car getCar(Integer id){
        return map.get(id);
    }
//    public Car createBean(){
//        return new Car();
//    }
//    public Car createBean1(){
//        return new Car();
//    }
}
  • xml文件配置
<?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: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-->
   <bean id="myfactory" class="com.cn.carfactory.InstanceFactory">

   </bean>
    <bean id="car" factory-bean="myfactory" factory-method="getCar">
        <constructor-arg value="2"/>

    </bean>
<!--    <bean id="car1" factory-bean="myfactory" factory-method="getCar">-->
<!--       <constructor-arg value="2"/>-->
<!--    </bean>-->

</beans>
  • 测试类
public class InstanceTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-instancefactory1.xml");
        Car car = (Car)context.getBean("car");
        System.out.println("car = " + car);
        //自己new一个实例对象
//        InstanceFactory instanceFactory = new InstanceFactory();
//        Car car = instanceFactory.getCar(3);
//        System.out.println("car = " + car);
    }
}
Ioc自动装载(Autowire)

Ioc负责创建对象,DI负责完成对象的依赖注入,通过配置property标签的ref属性来完成,同时spring还提供了一种另外更加简便的依赖注入方式:自动装载,不需要手动添加配置property,Ioc容器会自动选择bean完成注入工作
自动装载有两种方式

  • byName属性:通过属性名自动装载
    示例
    实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Car {
    private Integer id;
    private String name;
}

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
    private Integer id;
    private String name;
    private Car car;
}

xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<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">
    <!--这里的car类型bean中的id值对应上person实体类中的成员变量名,否则通过byName自动装配会失败-->
    <bean id="car" class="com.entity.Car">
        <property name="id" value="10"/>
        <property name="name" value="本田"/>
     </bean>
    <bean id="person" class="com.entity.Person" autowire="byName">
        <property name="id" value="11"/>
        <property name="name" value="李四"/>
    </bean>
</beans>

测试类

public class AutoWireBean {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-autowire.xml");
        Person person = (Person) context.getBean("person");
        System.out.println("person = " + person);
    }
}
  • byType属性:通过属性的数据类型自动装载
    实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Car {
    private Integer id;
    private String name;
}

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
    private Integer id;
    private String name;
    private Car car;
}

xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<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">
    <!--这里的id属性名称可以不跟依赖实体类的对象的属性变量名,可以随便取名字-->
    <bean id="cars" class="com.entity.Car">
        <property name="id" value="10"/>
        <property name="name" value="本田"/>
    </bean>
    <bean id="person" class="com.entity.Person" autowire="byType">
        <property name="id" value="11"/>
        <property name="name" value="李四"/>
    </bean>
</beans>

测试类

public class AutoWireBean {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-autowire.xml");
        Person person = (Person) context.getBean("person");
        System.out.println("person = " + person);
    }
}

其中byTye属性值需要注意的问题是:如果同时存在两个或者两个以上的符合的bean时,自动装载会报异常(不知道是取哪一个bean对象)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值