文章目录

  • 1. Bean的创建
  • 1.1 构造器注入
  • 1.2 不同类型的属性的set注入方式
  • 1.3 扩展方式注入
  • 1.4 XML文件中的其他配置属性
  • 2. Bean的作用域
  • 2.1 单例模式
  • 2.2 原型模式
  • 3. Bean的自动装配
  • 3.1 XML中显示配置
  • 3.2 Java代码中使用注解配置
  • 4. 使用全注解的方式实现类的配置


1. Bean的创建

  • SpringBean的创建主要实现理念是控制反转
  • SpringBean的创建主要实现方式是依赖注入
  • 依赖:Bean对象的创建依赖于容器
  • 注入:Bean对象的所有属性由容器来注入

依赖注入一共有三种方式

  1. 构造器注入
  2. Set方法注入
  3. 扩展方式

1.1 构造器注入

  1. 使用无参构造方法创建对象(默认是实现方式)
  2. 使用有参构造时,在XML文件中传入参数,有3种方式
<!--
    使用参数下标匹配:index代表参数下标,从0开始
    使用参数类型匹配:type代表参数类型,基本类型直接使用,引用必须是全部限定类名
    使用参数名:name代表构造函数中的参数名称
-->
<bean id="user" class="com.hust.pojo.User">
    <constructor-arg index="0" value="123"/>
    <constructor-arg type="java.lang.String" value="123"/>
    <constructor-arg name="name" value="123"/>
</bean>

在配置文件加载的时候,容器所管理的对象已经全部初始化了

1.2 不同类型的属性的set注入方式

  • 创建测试对象
public class Address {
    private String address;

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
    
    @Override
    public String toString() {
        return "Address{" +
                "address='" + address + '\'' +
                '}';
    }
}


public class Student {
    private String name;
    private Address address;
    private String[] books;
    private List<String> hobbys;
    private Map<String,String> card;
    private Set<String> games;
    private Properties info; //配置类型
    private String wife; //测试空指针

    public String getName() {
        return name;
    }

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

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    public String[] getBooks() {
        return books;
    }

    public void setBooks(String[] books) {
        this.books = books;
    }

    public List<String> getHobbys() {
        return hobbys;
    }

    public void setHobbys(List<String> hobbys) {
        this.hobbys = hobbys;
    }

    public Map<String, String> getCard() {
        return card;
    }

    public void setCard(Map<String, String> card) {
        this.card = card;
    }

    public Set<String> getGames() {
        return games;
    }

    public void setGames(Set<String> games) {
        this.games = games;
    }

    public Properties getInfo() {
        return info;
    }

    public void setInfo(Properties info) {
        this.info = info;
    }

    public String getWife() {
        return wife;
    }

    public void setWife(String wife) {
        this.wife = wife;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", address=" + address.toString() +
                ", books=" + Arrays.toString(books) +
                ", hobbys=" + hobbys +
                ", card=" + card +
                ", games=" + games +
                ", info=" + info +
                ", wife='" + wife + '\'' +
                '}';
    }
}
  • 不同类型属性值注入方式(applicationContext.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">

    <bean id="address" class="com.hust.pojo.Address">
        <property name="address" value="HUST"/>
    </bean>

    <bean id="student" class="com.hust.pojo.Student">
        <!--普通值注入,使用value赋值-->
        <property name="name" value="张三"/>
        <!--引用注入/Bean注入-->
        <property name="address" ref="address"/>
        <!--数组注入-->
        <property name="books">
            <array>
                <value>Java</value>
                <value>Python</value>
                <value>C++</value>
            </array>
        </property>
        <!--List集合注入-->
        <property name="hobbys">
            <list>
                <value>唱</value>
                <value>跳</value>
                <value>Rap</value>
                <value>篮球</value>
            </list>
        </property>
        <!--Map注入-->
        <property name="score">
            <map>
                <entry key="语文" value="95"/>
                <entry key="数学" value="98"/>
                <entry key="英语" value="97"/>
            </map>
        </property>
        <!--Set注入-->
        <property name="games">
            <set>
                <value>LOL</value>
                <value>FIFA</value>
                <value>NBA2K</value>
            </set>
        </property>
        <!--null值注入-->
        <property name="wife">
            <null />
        </property>
        <!--Properties注入,结构类似于Map,注入方式不一样-->
        <property name="info">
            <props>
                <prop key="学号">M202012123</prop>
                <prop key="班级">M2003班</prop>
            </props>
        </property>
    </bean>
    
</beans>
  • 测试类
public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //在getBean后面添加类的类型,可以不用强转
        Student student = context.getBean("student", Student.class);
        System.out.println(student);
    }
}

1.3 扩展方式注入

  • 分为p命名空间c命名空间两种方式,分别需要导入XML约束
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       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">

	<!--p命名空间方式-->
    <bean id="user1" class="com.hust.pojo.Student" p:name="LoveLin"/>
    <!--c命名空间方式,类中必须要有有参构造函数,否则会报错-->
    <bean id="user2" class="com.hust.pojo.Student" c:name="Melo"/>
>

1.4 XML文件中的其他配置属性

  1. 别名,在使用getBeans()时可以使用别名代替
  • alias:区分大小写,写在bean标签的外面,一对一的关系
  • name:写在bean标签里面,可以同时取多个别名(使用逗号,空格,分号分割都可以)
<alias name="mySQLImpl" alias="impl1"/>
<bean id="mySQLImpl" class="com.hust.dao.UserDaoMySQLImpl" name="impl1,im1;i1 1"/>
  1. 单例,使整个系统中只有一个实例
<bean id="mySQLImpl" class="com.hust.dao.UserDaoMySQLImpl" scope="singleton"/>
  1. import,一般用于团队开发,可以将多个配置文件导入合并为一个
<import resource="beans1.xml"/>
<import resource="beans2.xml"/>
<import resource="beans3.xml"/>

2. Bean的作用域

  • 在bean标签中添加scope属性可以指定作用域,默认为单例模式
  • requestsessionapplication只能在web开发中使用

2.1 单例模式

  • 默认即为单例模式,可以不写
<bean id="address" class="com.hust.pojo.Address" scope="singleton"/>

2.2 原型模式

  • 每次使用getBean()都会产生一个新的对象
<bean id="address" class="com.hust.pojo.Address" scope="prototype">

3. Bean的自动装配

Spring满足Bean依赖的一种方式,Spring会在上下文中自动寻找并自动装配,有3种装配的方式

  1. 在XML中显示配置
  2. 在Java中显示配置
  3. 隐式自动装配

3.1 XML中显示配置

  • 在bean标签里面有一个autowire属性;可以不用再在里面配置相关属性
  • byName:根据名称自动装配;类中属性名必须与配置文件中bean的id要一致,setDog==dog,需要bean的id唯一
<bean id="cat" class="com.hust.pojo.Cat"/>
    <bean id="dog" class="com.hust.pojo.Dog"/>

    <bean id="people" class="com.hust.pojo.People" autowire="byName">
        <property name="name" value="张三" />
        <!--<property name="cat" ref="cat" />
        <property name="dog" ref="dog" />-->
    </bean>
  • byType:根据属性的类型来装配,会自动寻找对应的类型,类中的id可以省略,但有多个相同类型时会报错
<bean class="com.hust.pojo.Cat"/>
    <bean class="com.hust.pojo.Dog"/>

    <bean id="people" class="com.hust.pojo.People" autowire="byType">
        <property name="name" value="张三" />
    </bean>

3.2 Java代码中使用注解配置

  • JDK1.5Spring2.5开始支持注解
  • 大部分情况下都会使用注解的方式来进行配置,更方便快捷,需要在XML文件中添加支持(beans导入约束,context添加支持)
<?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">
	<!--开启注解支持-->
    <context:annotation-config/>
 	<!--配置文件中只需要添加id和class属性-->
    <bean id="cat" class="com.hust.pojo.Cat"/>
    <bean id="dog" class="com.hust.pojo.Dog"/>
    <bean id="people" class="com.hust.pojo.People"/>
</beans>
  • 在需要自动导入的地方添加@Autowired注解
public class People {
    private String name;
    @Autowired
    private Cat cat;
    @Autowired
    private Dog dog;
	...
	//这种方式下可以不写对应属性的set方法
}
  • @Autowired注解里面有一个required属性,默认为true,如果设置为false,则说明这个属性可以为null,否则不能为空
@Autowired(required = false)
private Dog dog;
  • 如果@Autowired自动装配的环境比较复杂,自动装配无法通过一个注解完成,则我们可以使用@Qualifiler(value="xxx")来指定唯一的注入对象
<!--此时自动装配无法自动识别装配对象-->
<!--如果里面有一个就是cat,则还是会运行成功,因为注解是根据byName来进行装配的-->
<bean id="cat1" class="com.hust.pojo.Cat"/>
<bean id="cat2" class="com.hust.pojo.Cat"/>
<bean id="dog1" class="com.hust.pojo.Dog"/>
<bean id="dog2" class="com.hust.pojo.Dog"/>
<bean id="people" class="com.hust.pojo.People"/>
@Autowired
@Qualifier(value = "cat1")
private Cat cat;
  • 此外,也可以使用@Resoure(name="xxx")来进行指定
@Resource(name="dog2")
private Dog dog

@Resource@Autowired的区别:

  1. 都是用于自动装配的,都可以放在属性的字段上面
  2. @Autowired自动通过byName的方式实现装配;是Spring中的注解
  3. @Resource先通过byName装配,如果不匹配则通过byType,是Java中的注解

4. 使用全注解的方式实现类的配置

  1. 编写需要装配的类,需要被扫描到
//说明这个类被Spring管理
@Component
public class User {
    private String name;

    public String getName() {
        return name;
    }
	//注入属性值
    @Value("aaa")
    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }
}
  1. 需要创建config类
//这是一个配置类,类似于xml文件,也会被Spring管理,本质也是一个@Component
@Configuration
//要扫描的包
@ComponentScan("com.hust.pojo")
public class MyConfig {
	//注册一个bean,相当于xml中的一个bean标签
    @Bean
    //这个方法的名字就相当于bean标签中的id属性
    //这个方法的返回值就相当于bean标签中的class属性
    public User getUser(){
    	//返回要注入的bean对象
        return new User();
    }
}
  1. 使用config获取context
public class MyTest {
    public static void main(String[] args) {
        //完全使用配置类的方式去获取context的方法
        ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
        System.out.println(context.getBean("getUser", User.class).getName());
    }
}