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();
}
}