新建一个mavean工程,引入依赖,并在resources下建立.xml文件
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<!--日志-->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>compile</scope>
</dependency>
</dependencies>
1.IOC的概念与原理
IOC 控制反转,把对象创建与对象调用之间的过程交给Spring容器进行管理,从而降低各模块之间的耦合度,其底层实现是?工厂模式+反射+xml解析。
?来简单的一个例子来理解一下控制反转, 新建四个包.bean,.service,.test,.dao
public class User {
private String name;
private int age;
public User() {
}
}
public interface UserDao {
void getUser();
}
public class UserDaoImpl implements UserDao{
@Override
public void getUser() {
System.out.println("UserDao~~");
}
}
public interface UserService {
void getUser();
}
public class UserServiceImpl implements UserService {
private UserDao userDao = new UserDaoImpl();
@Override
public void getUser() {
userDao.getUser();
}
在这个过程中,Service层只做了一件事就是调用Dao层,但我们现在在Dao层在增加一个接口和它的实现类
public interface UserTwoDao {
void getUser();
}
public class UserTwoDaoImpl implements UserTwoDao{
@Override
public void getUser() {
System.out.println("The Second User");
}
}
那么service层相应变为
public class UserServiceImpl implements UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void getUser() {
userDao.getUser();
}
}
用户可以根据需求选择合适的UserDao的实现类,由程序员自行创建对象,程序只负责提供一个接口,这就是Ioc的原型。控制反转就是通过扫描注解或者xml文件,并通过第三方来获取特定对象的方式,String的IOC容器实现了控制反转。
用IOC来快速获取对象? (IOC默认的是通过空参构造器来获取对象,如果要用有参构造需提供set方法,用set注入引用新的名称空间)application.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
http://www.springframework.org/schema/p">
<!--通过无参构造来创建User对象-->
<bean id="user" class="com.atugi.bean.User"></bean>
<!--2 set方法注入属性-->
<bean id="user" class="com.atugi.bean.User">
<!--使用property完成属性注入
name:类里面属性名称
value:向属性注入的值
-->
<property name="name" value="陈二狗"></property>
<property name="age" value="19"></property>
<!--null值-->
<!--<property name="">
<null/>
</property>-->
</bean>
<!--3 有参数构造注入属性-->
<bean id="orders" class="com.atugi.bean.User">
<constructor-arg name="name" value="陈二狗"></constructor-arg>
<constructor-arg name="age" value="19"></constructor-arg>
</bean>
<!--2 set方法注入属性-->
<bean id="user" class="com.atugi.bean.User" p:name="九阳神功" p:age="18">
</bean>
</beans>
public class testBean {
@Test
public void test(){
/*
Spring 提供 IOC 容器实现两种方式:(两个接口)
(1)BeanFactory:IOC 容器基本实现,是 Spring 内部的使用接口,不提供开发人员进行使用
加载配置文件时候不会创建对象,在获取对象(使用)才去创建对象
(2)ApplicationContext:BeanFactory 接口的子接口,提供更多更强大的功能,一般由开发人员进行用
加载配置文件时候就会把在配置文件对象进行创建
*/
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = context.getBean("user", User.class);
System.out.println(user);
}
}
?IOC管理bean
2.1.注入属性,外部bean
<bean id="UserServiceImpl" class="com.atugi.service.UserServiceImpl">
<property name="userDao" ref="userDao"></property>
</bean>
<bean id="userDao" class="com.atugi.dao.UserDaoImpl"></bean>
public class testBean {
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserServiceImpl user = context.getBean("UserServiceImpl", UserServiceImpl.class);
user.getUser();
}
}
2.2 注入内部bean?
//部门类
public class Dept {
private String dname;
public void setDname(String dname) {
this.dname = dname;
}
}
//员工类
public class Emp {
private String ename;
private String gender;
//员工属于某一个部门,使用对象形式表示
private Dept dept;
public void setDept(Dept dept) {
this.dept = dept;
}
public void setEname(String ename) {
this.ename = ename;
}
public void setGender(String gender) {
this.gender = gender;
}
}
<bean id="emp" class="com.atugi.bean.Emp">
<!--设置两个普通属性-->
<property name="ename" value="lucy"></property>
<property name="gender" value="女"></property>
<!--级联赋值-->
<property name="dept" ref="dept"></property>
</bean>
<bean id="dept" class="com.atugi.bean.Dept">
<property name="dname" value="财务部"></property>
</bean>
2.3注入数组
public class Stu {
//1 数组类型属性
private String[] courses;
//2 list 集合类型属性
private List<String> list;
//3 map 集合类型属性
private Map<String,String> maps;
//4 set 集合类型属性
private Set<String> sets;
public void setSets(Set<String> sets) {
this.sets = sets;
}
public void setCourses(String[] courses) {
this.courses = courses;
}
public void setList(List<String> list) {
this.list = list;
}
public void setMaps(Map<String, String> maps) {
this.maps = maps;
}
}
<!--1 集合类型属性注入-->
<bean id="stu" class="com.atugi.collectiontype.Stu">
<!--数组类型属性注入-->
<property name="courses">
<array>
<value>java 课程</value>
<value>数据库课程</value>
</array>
</property>
<!--list 类型属性注入-->
<property name="list">
<list>
<value>张三</value>
<value>小三</value>
</list>
</property>
<!--map 类型属性注入-->
<property name="maps">
<map>
<entry key="JAVA" value="java"></entry>
<entry key="PHP" value="php"></entry>
</map>
</property>
<!--set 类型属性注入-->
<property name="sets">
<set>
<value>MySQL</value>
<value>Redis</value>
</set>
</property>
</bean>
把集合注入部分提取出来
(1)在 spring 配置文件中引入名称空间 util
<?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"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
(2)使用 util 标签完成 list 集合注入提取
<!--1 提取 list 集合类型属性注入-->
<util:list id="bookList">
<value>易筋经</value>
<value>九阴真经</value>
<value>九阳神功</value>
</util:list>
<!--2 提取 list 集合类型属性注入使用-->
<bean id="book" class="com.atguigu.spring5.collectiontype.Book">
<property name="list" ref="bookList"></property>
</bean>
2.4 bean生命周期
<bean id="orders" class="com.atugi.bean.Order" init-method="initMethod" destroy-method="destroyMethod">
<property name="name" value="手机"></property>
</bean></beans>
public class Order {
private String name;
public Order(String name) {
this.name = name;
}
public Order() {
System.out.println("第一步 执行无参数构造创建 bean 实例");
}
public void setName(String name) {
this.name = name;
System.out.println("第二步 调用 set 方法设置属性值");
}
//创建执行的初始化的方法
public void initMethod() {
System.out.println("第三步 执行初始化的方法");
}
//创建执行的销毁的方法
public void destroyMethod() {
System.out.println("第五步 执行销毁的方法");
}
}
public class testBean {
@Test
public void test(){
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
Order orders = context.getBean("orders", Order.class);
System.out.println("第四步 获取创建 bean 实例对象");
System.out.println(orders);
//手动让 bean 实例销毁
context.close();
}
}
public class MyBeanPost implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
System.out.println("在初始化之前执行的方法");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
System.out.println("在初始化之后执行的方法");
return bean;
}
}
(1)通过构造器创建 bean 实例(无参数构造)
(2)为 bean 的属性设置值和对其他 bean 引用(调用 set 方法)
(3)把 bean 实例传递 bean 后置处理器的方法 postProcessBeforeInitialization
(4)调用 bean 的初始化的方法(需要进行配置初始化的方法)
(5)把 bean 实例传递 bean 后置处理器的方法 postProcessAfterInitialization
(6)bean 可以使用了(对象获取到了) (
(7)当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法)?
3. 注解实现
Spring 针对 Bean 管理中创建对象提供注解(功能一样,为了规范建议对应使用)
(1)@Component (2)@Service (3)@Controller (4)@Repository
3.1.开启组件扫描
<context:component-scan base-package="com.atguigu"></context:component-scan>
3.2.用注解实现 属性注入
(1)@Autowired:根据属性类型进行自动装配?
(2)@Qualifier:根据名称进行注入 这个@Qualifier 注解的使用,和上面@Autowired 一起使用?
????????@Autowired //根据类型进行注入 @Qualifier(value = "userDaoImpl1") //根据名称进行注入
(3)@Resource:可以根据类型注入?@Resource(name = "userDaoImpl1")
(4)@Value:注入普通类型属性?@Value(value = "abc")
4.可以用完全注解进行开发
//(1)创建配置类,替代 xml 配置文件
@Configuration //作为配置类,替代 xml 配置文件
@ComponentScan(basePackages = {"com.atugi"})
public class SpringConfig {
}
//(2)编写测试类
@Test
public void testService2() {
//加载配置类
ApplicationContext context
= new AnnotationConfigApplicationContext(SpringConfig.class);
UserService userService = context.getBean("userService",
UserService.class);
System.out.println(userService);
userService.add();
}
|