Spring IoC、DI、Bean和自动装配的理解

IoC创建对象

我们都知道IoC是控制反转的,也就是我们只需要把类注册到Spring容器中,他可以帮助我们创建对象,该创建的思想也就是走的构造器
通过XML
例如我们创建一个People对象,默认有一个无参构造

package com.hzy.pojo;
public class People {
}

然后我们通过XML将该类注册到Spring中,这样他就是一个bean了,并且被Spring管理
<bean id="people" class="com.hzy.pojo.People"/>
我们进行创建对象的时候,不用new了,而是在Spring容器中拿

ApplicationContext context2 = new ClassPathXmlApplicationContext("applicationContext.xml");
People people = context2.getBean("people", People.class);

通过注解
在用注解之前,我们需要先打开注解的支持和注解要扫描的包

<!--    开启注解支持-->
<context:annotation-config/>
<!--    配置要扫描的包下的注解生效-->
<context:component-scan base-package="com.hzy.pojo"/>

然后创建类,通过@Component注入到Spring,与此作用一样的还有@Service、@Controller、@Repository

package com.hzy.pojo;

import org.springframework.stereotype.Component;

@Component
public class People {
}

获取的时候同样

ApplicationContext context2 = new ClassPathXmlApplicationContext("applicationContext.xml");
People people = context2.getBean("people", People.class);
System.out.println(people);

通过完全注解
首先我们需要创建一个配置类AppConfig,名字可以随便取,在这个配置类中,就把要注入Spring中的类当作一个bean了

package com.hzy.config;

import com.hzy.pojo.People;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {
    @Bean
    public People people() {
        return new People();
    }
}

然后就只需要创建一个类,这里不用@Component注解了,因为在配置类中已经指定类了。

package com.hzy.pojo;

public class People {
}

最后测试的时候用AnnotationConfigApplicationContext

ApplicationContext context2 = new AnnotationConfigApplicationContext(AppConfig.class);
People people = context2.getBean("people", People.class);

DI依赖注入

依赖注入这里主要讲解set注入和构造器注入
set注入
在我们进行XML创建对象的时候,我们可以通过property标签进行值得注入
首先我们创建一个普通的实体类

package com.hzy.pojo;

public class Student {
    private String name;
    private int age;
	// get set tostring 省略
}

然后在XML中进行配置即可

<bean id="student" class="com.hzy.pojo.Student">
    <property name="name" value="张三"/>
    <property name="age" value="18"/>
</bean>

另外,我们还可以通过p(property)命名空间
<bean id="student" class="com.hzy.pojo.Student" p:name="张三" p:age="18"/>
记得引入一个头文件
xmlns:p="http://www.springframework.org/schema/p"
另外我们还可以通过注解进行注入
首先在XML中开启注解并配置要扫描的包

<!--    开启注解支持-->
<context:annotation-config/>
<!--    配置要扫描的包下的注解生效-->
<context:component-scan base-package="com.hzy.pojo"/>

注解可以写到属性上,也可以写到set方法上

package com.hzy.pojo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class Student {
    @Value("张三")
    private String name;
    @Value("18")
    private int age;
	// 省略get set toString
}

我们还可以通过无配置文件注入,也就是先创建一个配置类,可以通过@ComponentScan配置要扫描的包,不配默认全部扫描

package com.hzy.config;

import com.hzy.pojo.Student;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(basePackages = {"com.hzy.pojo"})
public class AppConfig {
    @Bean
    public Student student() {
        return new Student();
    }
}

构造器注入
构造器注入需要我们提供一个有参构造方法

package com.hzy.pojo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

public class Teacher {

    private String name;
    private Integer age;

    public Teacher(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
    @Override
    public String toString() {
        return "Teacher{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

在配置文件中通过constructor-arg属性注入值

<bean id="teacher" class="com.hzy.pojo.Teacher">
    <constructor-arg name="name" value="张三"/>
    <constructor-arg name="age" value="18"/>
</bean>

或者通过c(constructor-arg)命名空间
<bean id="teacher" class="com.hzy.pojo.Teacher" c:name="张三" c:age="18"/>

Bean的理解

首先说Bean的作用域,常用的有singleton单例,prototype原型,也就是多例
<bean id="teacher" class="com.hzy.pojo.Teacher" scope="singleton"/>
<bean id="teacher" class="com.hzy.pojo.Teacher" scope="prototype"/>
如果有线程安全问题,用prototype
另外就是关于Bean的生命周期,一共可以分为七步
1、构造器构造实例
2、注入值
3、初始化之前执行后置处理器的before方法,即实现BeanPostProcesser
4、初始化init-method
5、初始化之后执行后置处理器的after方法,即实现BeanPostProcesser
6、可以使用
7、销毁destory-method

自动装配

我们可以在配置文件中配置
<bean id="teacher" class="com.hzy.pojo.Teacher" autowire="byType"/>
<bean id="teacher" class="com.hzy.pojo.Teacher" autowire="byName"/>
但是我们一般都是用注解
@Autowired 默认是byType,可以通过@Qualifile为byName
@Resource 默认是byName,找不到自动byType
举例:我们头通过自动装配在service层注入dao
首先在配置文件中开启注解的支持和要扫描的包,这里也可以通过配置类

<!--    开启注解支持-->
<context:annotation-config/>
<!--    配置要扫描的包下的注解生效-->
<context:component-scan base-package="com.hzy"/>

首先我们写一个UserDao接口

package com.hzy.dao;

public interface UserDao {
    public void add();
}

然后写一个实现类,该类通过@Repository注入到Spring中

package com.hzy.dao;

import org.springframework.stereotype.Repository;

@Repository
public class UserDaoImpl implements UserDao {
    public void add() {
        System.out.println("add ...");
    }
}

然后就是业务层@Service,调用dao层,此处自动装配的UserDao

package com.hzy.service;

import com.hzy.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    @Autowired
    private UserDao userDao;
    public void add() {
        userDao.add();
    }
}

最后测试

public class MyTest {
    @Test
    public void myTest() {
        ApplicationContext context1 = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = context1.getBean("userService", UserService.class);
        userService.add();
    }
}

在这里插入图片描述
如果我们在UserDaoImpl指定name的名字,然后并且用@AutoWired装配

@Repository("abc")
public class UserDaoImpl implements UserDao {
    public void add() {
        System.out.println("add ...");
    }
}

@Service
public class UserService {

    @Autowired
    @Qualifier("abc") //与上面的对应
    private UserDao userDao;
    public void add() {
        userDao.add();
    }

}

同时我们也可以通过@Resource

@Service
public class UserService {

//    @Autowired
//    @Qualifier("abc")
    @Resource(name = "abc")
    private UserDao userDao;
    public void add() {
        userDao.add();
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

贺志营

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

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

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

打赏作者

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

抵扣说明:

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

余额充值