Spring三种对象创建方式

1. 无参构造

首先我们先创建一个User类

public class User {
    private String name;
    private int age;
    public User() {
        System.out.println("无参构造方法");
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }

}

在spring的环境配置文件里配置

<bean name="user" class="cn.it.bean.User"></bean>
2. 静态工厂

创建一个UserFactory类,代码如下

public class UserFactory {
    public static User createUser() {
        System.out.println("静态工厂");
        return new User();
    }
}

在配置文件里配置

<!-- 调用静态工厂 -->
<bean name="user2" class="cn.it.create.UserFactory" factory-method="createUser"/>
3. 实例工厂

在上面的UserFactory改成如下代码

public class UserFactory {
    public static User createUser() {
        System.out.println("静态工厂");
        return new User();
    }

    public  User createUser2() {
        System.out.println("实例工厂");
        return new User();
    }
}

在配置文件里配置

<!-- 调用实例工厂 -->

<bean name="user3" factory-bean="userFactory" factory-method="createUser2"></bean>
<bean name="userFactory" class="cn.it.create.UserFactory"></bean>

上面三种创建方式已经准备好了,接下来我们写一个测试类

public class Demo {
    @Test
    //创建方法一:空参构造
    public void fun1() {
        //每次容器启动就会创建容器中所配置的所有对象
        ApplicationContext as = new ClassPathXmlApplicationContext("cn/it/create/applicationContext.xml");
        User user = (User) as.getBean("user");
        System.out.println(user);
    }
    @Test
    //创建方法二:静态工厂
    public void fun2() {
        //每次容器启动就会创建容器中所配置的所有对象
        ApplicationContext as = new ClassPathXmlApplicationContext("cn/it/create/applicationContext.xml");
        User user = (User) as.getBean("user2");
        System.out.println(user);
    }
    @Test
    //创建方法二:实例工厂
    public void fun3() {
        //每次容器启动就会创建容器中所配置的所有对象
        ApplicationContext as = new ClassPathXmlApplicationContext("cn/it/create/applicationContext.xml");
        User user = (User) as.getBean("user3");
        System.out.println(user);
    }
}

Bean的装配方式

1. 基于XML的装配

首先创建一个实体类User

package com.iteima.assemable;

import java.util.List;

public class User {
    private String username;
    private Integer password;
    private List<String> list;
    /**
     * 1 使用构造注入
     * 1.1 提供带所有参数的有参构造方法
     */
    public User(String username, Integer password, List<String> list) {
        this.username = username;
        this.password = password;
        this.list = list;
    }
    /**
     * 2 使用设置注入
     * 2.1 提供默认空参数构造方法
     * 2.2 为所有属性提供setter方法
     */
    public User(){
        super();
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setPassword(Integer password) {
        this.password = password;
    }

    public void setList(List<String> list) {
        this.list = list;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", password=" + password +
                ", list=" + list +
                '}';
    }
}

创建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">

    <!--1.使用构造注入方式装配User实例-->
    <!-- public User(String username, Integer password, List<String> list)-->
    <bean id="user1" class="com.iteima.assemable.User">
        <constructor-arg index="0" value="tom"/>
        <constructor-arg index="1" value="123456"/>
        <constructor-arg index="2">
            <list>
                <value>"constructorvalue1"</value>
                <value>"constructorvalue2"</value>
            </list>
        </constructor-arg>
    </bean>
    <!--2.使用设值注入方式装配User实例-->
    <bean id="user2" class="com.iteima.assemable.User">
        <property name="username" value="张三"></property>
        <property name="password" value="654321"></property>
        <!--注入list集合-->
        <property name="list">
            <list>
                <value>"setlistvalue1"</value>
                <value>"setlistvalue2"</value>
            </list>
        </property>
    </bean>
</beans>

创建一个测试类

package com.iteima.assemable;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class XmlBeanAssembleTest {
    public static void main(String[] args) {
        //加载配置文件
        ApplicationContext applicationContext = new                             ClassPathXmlApplicationContext("bean.xml");
        //构造方式输出结果
        System.out.println(applicationContext.getBean("user1"));
        //设值方式输出结果
        System.out.println(applicationContext.getBean("user2"));
    }
}

2. 自动装配

虽然使用注解的方式装配Bean,在一定程度上减少了配置文件的代码量,但是也有企业项目中,是没有使用注解方式开发的,那么有没有什么办法既可以减少代码量,又能够实现Bean的装配呢?

答案是肯定的,Spring的<bean>元素中包含一个autowire属性,我们可以通过设置autowire属性值来自动装配Bean。所谓自动装配,就是将一个Bean自动地注入到其他Bean的Propert中。</bean>

引用类型的自动注入:spring框架根据某些规则可以给引用类型赋值,不用你在给引用类型赋值了。

使用的规则常用的是byName,byType。

  • byName(按名称注入):Java类中引用类型的属性名和spring容器中(配置文件)<bean>的id名称一样,且数据类型是一致的,这样的容器中的bean,spring能够赋值给引用类型。</bean>
  • 语法:
<bean id="xx" class="yyy" autowire="byName">
   简单类型属性赋值
</bean>
  • byType(按类型注入):Java类中引用类型的数据类型和spring容器中(配置文件)<bean>的class属性是同源就是一类的意思:</bean>

    • Java类中引用类型的数据类型和bean的class的值是一样的。
    • Java类中引用类型的数据类型和bean的class的值父子类关系的。
    • Java类中引用类型的数据类型和bean的class的值接口和实现类关系的。
    • 语法:
<bean id="xx" class="yyy" autowire="byType">
   简单类型赋值
</bean>

3. 基于注解的装配

组件扫描器

声明组件扫描器(component-scan),组件就是Java对象

  • base-package:指定注解在你的项目中的包名。
  • component-scan工作方式:spring会扫描遍历base-package指定的包,把包中和子包中的所有

​ 类,找到类中的注解,按照注解的功能创建对象,或给属性赋值。

<context:component-scan base-package="com.ithime.bean"/> 
注解 作用
@Component 可以使用此注解描述Spring中的Bean,但它是一个泛化的概念,仅仅表示一个组件(Bean),并且可以作用在任何层次。使用时只需将该注解标注在相应的类上即可。
@Repository 用于将数据访问层(DAO层)的类标识为Spring中的Bean,其功能与@Component相同。
@Service 通常作用在业务层(Service层),用于将业务的类标识为Spring中的Bean,其功能与@Component相同。
@Controller 通常作用在控制层(如SpringMVC的Controller),用于将控制层的类标识为Spring中的Bean,其功能与@Component相同。
@Autowired 用于对Bean的属性变量、属性的setter方法及构造方法进行标注,配合对应的注解处理器完成Bean的自动配置工作。默认按照Bean的类型进行装配。

补充:

@Component:创建对象的,等同于<bean>的功能</bean>

​ 属性:value就是对象的名称,也就是bean的id值,value的值是唯一的,创建的对象在整个spring

​ 容器中就一个。

​ 位置:在类的上面。

@Component(value = "myStudent")等同于

<bean id="myStudent" class="com.ithime.bean.Student"/>

spring中和@Component功能一致,创建对象的注解还有:

  • @Repository(用在持久层类的上面):放在dao的实现类上面,表示创建dao对象,dao对象是能访问数据库的。
  • @Service(用在业务层类的上面):放在Service的实现类上面,创建Service对象,Service对象做业务处理,可以有事务等功能表的。
  • @Controller(用于控制器的上面):放在控制器(处理器)类的上面,创建控制器对象的,控制器对象,能够接受用户提交的参数,显示请求的处理结果。

以上三个注解的使用语法和@Component一样的,都能创建对象,但是这三个注解还有额外的功能。