文章目录
一、Spring框架基础
详细介绍(http://codepub.cn/2015/06/21/Basic-knowledge-summary-of-Spring/)
Spring框架的核心功能有两个
- Spring容器作为超级大工厂,负责创建、管理所有的Java对象,这些Java对象被称为Bean
- Spring容器管理容器中Bean之间的依赖关系,Spring使用一种被称为“依赖注入”的方式来管理Bean之间的依赖关系
使用依赖注入,不仅可以为Bean注入普通的属性值,还可以注入其他Bean的引用。依赖注入是一种优秀的解耦方式,其可以让Bean以配置文件组织在一起,而不是以硬编码的方式耦合在一起。
1.Spring的特点及体系结构
Spring的核心是依赖注入(Dependency Injection,DI) 、控制反转(Inversion of Control, Ioc)、面向切面编程(Aspect-Oriented Programming, AOP )。Spring是一个分层的Java SE/EE full-stack(一站式)轻量级开源框架。
(1)Spring6点优势:
- 方便解耦,简单化开发(ico)(https://www.cnblogs.com/xdp-gacl/p/4249939.html) 把创建对象的过程交给Spring进行管理
- AOP编程的支持 不修改源代码的情况下 进行功能的增强
- 声明式事务的支持
- 方便程序的测试
- 方便集成各种优秀的框架
- 降低Java EE API的使用难度
(2)Spring的体系结构:
详细结构介绍https://www.w3cschool.cn/wkspring/dcu91icn.html
#maven 导入Spring坐标依赖(idea)
<!-- spring5.3.3依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.3</version>
</dependency>
二、实例化Bean对象
1.无参构造 通常简单形式注册Bean容器
//java.class
public class UserDaoImpl implements UserDao {
@Override
public void save() {
System.out.println("save Running....");
}
public void init(){
System.out.println("初始化方法!");
}
public void destroy(){
System.out.println("销毁方法!");
}
}
<!-- spring-xml -->
<!-- 注册容器 后面通过getBean("容器的id")来调用对象 而不是像java面向对象一样new xx();一个对象来调用 这样解耦性较强!-->
<!-- id属性值 是自定义的 但规范写法是 实现类的小写名称 -->
<bean id="userDao" class="com.xqh.dao.impl.UserDaoImpl" init-method="init" destroy-method="destroy"></bean>
<!-- init-method为初始化方法 ,destro-method为销毁方法 两个方法在 注册容器 是可写可不写的 -->
2.静态和动态工厂创建Bean对象
/*
静态工厂
*/
public class StaticFactory {
public static UserDao getUserDao(){
return new UserDaoImpl();
}
}
/*
动态工厂
*/
public class DynamicFactroy {
public UserDao getUserDao(){
return new UserDaoImpl();
}
}
<?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">
<!-- 工厂静态实例化bean 类似于java静态方法的调用 类名.方法-->
<bean id="userDao" class="com.xqh.factory.StaticFactory" factory-method="getUserDao"></bean>
<!-- 工厂动态 实例化Bean 类似于java对象的方法的调用 先创建实体类 再用变量名.方法调用-->
先声明工厂变量 在使用变量
<bean id="dynamicFactroy" class="com.xqh.factory.DynamicFactroy"></bean>
<bean id="userDao" factory-bean="dynamicFactroy" factory-method="getUserDao"></bean>
</beans>
//测试类
@Test
public void test01(){
//返回类型Class为实现的子类方法具体
//applica为父类无close方法
ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao = (UserDao) app.getBean("userDao");//参数为bean容器的 id属性 千万不要写错 做好复制张贴!
userDao.save();
// app.close();//销毁方法 提示容器执行类中销毁方法 在销毁容器
}
三.Spring属性注入
1.set注入
使用bean的子标签property
//java.class
//第一个类
public class Person {
private String name;
private String sex;
private Car car;//引用类
public void setCar(Car car) { //引用类set注入必写
this.car = car;
}
public void setName(String name) {//set方法的名字 name(不要set 小写name)!!! 实现类要用set注入必须写set()方法
this.name = name;
}
public void setSex(String sex) {
this.sex = sex;
}
}
//引用类
public class Car {
private String name;
private String color;
public void setName(String name) {
this.name = name;
}
public void setColor(String color) {
this.color = color;
}
}
<!-- spring-xml -->
<!-- 引用类 注册容器 并且注入值-->
<bean id="car" class="com.xqh.pojo.Car">
<property name="name" value="法拉利"/>
<property name="color" value="red"/>
</bean>
<bean id="personSetDi" class="com.xqh.pojo.Person">
<!-- name属性=set方法的set名字!!! 而不是类的属性名 value="你想给的自定义值" ref=引入的beanID属性值 应用类-->
<property name="name" value="xqh"/>
<property name="sex" value="man"/>
<!-- 引用时 name属性值依旧是 类中set方法的名字 ref属性值为=> 对应已注册的beanID值 car-->
<property name="car" ref="car"/>
</bean>
<!-- 注意这里的 set注入 name 是<bean>子标签<property>中的属性name 而不是<bean>标签中的属性name !!!初学容易混乱-->
2.有参构造方法注入
使用子标签constructor-arg
package com.xqh.pojo;
public class Person {
private String name;
private String sex;
public Person(String name, String sex) {
this.name = name;
this.sex = sex;
}
<!-- 构造函数DI依赖注入-->
<bean id="personConstructorDi" class="com.xqh.pojo.Person">
<constructor-arg name="name" value="yuyan"/>
<constructor-arg name="sex" value="woman"/>
</bean>
3.p命名空间注入属性
使用bean 属性p:实体类中属性对应的set方法名="" (可以理解为set注入的简写)
<!-- p命名空间注入对象-->
<bean id="userDao" class="com.xqh.dao.impl.UserDaoImpl"></bean>-->
<bean id="userService" class="com.xqh.service.impl.UserServiceImpl" p:userDao-ref="userDao"/>
<!-- p:命名空间注入普通属性-->
<bean id="pUser" class="com.xqh.pojo.User" p:userName="aaa" p:password="321"></bean>
4.spel表达式注入属性
<!-- spel表达式注入属性-->
<bean id="spelUser" class="com.xqh.pojo.User">
<property name="userName" value="#{'acer'}"/>
<property name="password" value="#{'123'}"/>
</bean>
四、BeanFactory接口和ApplicationContext接口的区别
BeanFactory是spring的原始接口,针对原始结构的实现类功能比较单一,BeanFactory接口实现的容器,
特点是在每次获取对象时才会创键
ApplicationContext 继承了BeanFactory接口,拥有BeanFactory的全部功能,并且扩展了很多高级特性,
特点每次容器启动时就会创建所有的对象。
ps:早期的电脑性能低,内存小,所以spring容器的容量不足,不能讲所以的对象全部创建好放入容器,所以使用的是BeanFactory,需要某个对象时,再进行创建,随着电脑硬件的发展,内存越来越大,所以spring框架引入了ApplicationContext,将所有的对象都创建好,放入容器,使用哪个对象,从容器中取得即可。
@Test
public void constructionDiTest01(){
ApplicationContext app = new ClassPathXmlApplicationContext("springXml/applicationContext.xml");
Person person = (Person) app.getBean("personConstructorDi");
System.out.println(person.getName()+"\n"+person.getSex());
}