Spring
1、spring框架概述
Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器(框架)
- Spring是为了构建企业应用的轻量级框架
- spring中的两大核心:IOC、AOP
2、spring的组成
Spring 框架是一个分层架构,由 7 个定义良好的模块组成。Spring 模块构建在核心容器之上,核心容器定义了创建、配置和管理 bean 的方式 .
2.1、核心容器
核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory,它是工厂模式的实现
-
2.2、spring上下文
Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息;例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。
-
2.3、SpringAOP
通过配置管理特性,Spring AOP 模块直接将面向切面的编程功能 , 集成到了 Spring 框架中
-
2.4、SpringDAO
JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息,Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。
-
2.5、Spring ORM
Spring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。
-
2.6、Spring Web 模块
Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文
-
2.7、Spring MVC 框架
MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。
3、IOC
回顾以往代码
//1.首先创建一个dao的接口
public interface IAccountDao {
void saveAccount();
}
//2.创建dao接口的实现类
public class AccountDaoImpl implements IAccountDao {
@Override
public void saveAccount() {
System.out.println("保存账户成功");
}
}
//3.创建业务层的接口
public interface IAccountService {
void saveAccount();
}
//4.创建业务层的实现类,通过业务层实现类调用dao接口获取实现类中的调用DB得到的具体数据进行业务操作
public class AccountServiceImpl implements IAccountService {
private IUserDao userDao = new UserDaoImpl();
@Override
public void saveAccount() {
userDao.findAll();
}
}
此时,代码间除了类与类间的耦合性过高,还存在这一个问题就是,每创建一个dao接口,在service层就会new一个dao对象,造成对象实例化次数过高,造成资源不必要的浪费;
/*
创建一个工厂,每当需要使用dao实例时,由工厂进行生产,生产后的实例交于需要的接口或实现类
*/
public class BeanFactory {
private static Properties properties = null;
private static Map<String,Object> beanMap = null;
static {
try {
properties = new Properties();
beanMap = new HashMap<>();
//加载bean.properties配置文件中的信息,该配置文件中配置为:类名为key,value为全限定类名
properties.load(BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties"));
//获取配置文件中的所有的类
Enumeration<Object> keys = properties.keys();
//遍历
while (keys.hasMoreElements()){
String key = keys.nextElement().toString();
//通过properties对象的方法获取对应类名的全限定名
String beanPath = properties.getProperty(key);
//将全限定名进行过实例化,value为该全限定名对应的实例
Object value = Class.forName(beanPath).newInstance();
//将类名与实例存入map对象中
beanMap.put(key,value);
}
} catch (IOException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
//该方法获取工厂所创建的实例对象
public static Object getInstance(String name){
//通过 传入的类型首字母小写获取 到对应的实例对象,为单例对象!
return beanMap.get(name);
}
}
public class AccountServiceImpl implements IAccountService {
@Override
public void saveAccount() {
//通过传入的变量名获取对应的实例对象,该对象为单例对象
IAccountDao accountDao = (IAccountDao)BeanFactory.getInstance("accountDao");
System.out.println("accountDao"+accountDao);
accountDao.saveAccount();
}
}
3.1、IOC的概念
- 控制反转IoC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法
- 控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)
- 意思为创建对象的权力由自身创建转变为交给工厂模式创建对象所需要的实例,这种权力的转变就成为控制反转;
3.2、ioc入门案例
-
在pom.xml文件中配置spring对应坐标
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.0.RELEASE</version> </dependency> </dependencies>
-
创建bean.xml配置文件并导入springioc约束
<?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标签就代表这是一个java对象,将该对象交由spring接管--> <bean id="accountService" class="com.wql.service.impl.AccountServiceImpl"/> <bean id="accountDao" class="com.wql.dao.impl.AccountDaoImpl"/> </beans>
-
获取容器对象二部曲
//1.通过ClassPathXmlApplicationContext对象加载bea对象配置文件 ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); //2.通过getBean方法获取反射对象所创建的接口对象 IAccountDao accountDao = (IAccountDao)ac.getBean("accountDao"); //3.执行方法 System.out.println(accountDao); IAccountService accountService = ac.getBean("accountService",IAccountService.class); System.out.println(accountService);
3.3、ioc创建对象的方式
-
无参构造函数创建
<!--默认创建--> <bean id="accountService" class="com.wql.service.impl.AccountServiceImpl"/>
-
有参创建
1、根据参数下标创建
<!-- 第一种根据index参数下标设置 --> <bean id="userT" class="com.kuang.pojo.UserT"> <!-- index指构造方法 , 下标从0开始 --> <constructor-arg index="0" value="kuangshen2"/> </bean>
2、根据参数名称创建
<!-- 第二种根据参数名字设置 --> <bean id="userT" class="com.kuang.pojo.UserT"> <!-- name指参数名 --> <constructor-arg name="name" value="kuangshen2"/> </bean>
3、根据参数类型创建
<!-- 第三种根据参数类型设置 --> <bean id="userT" class="com.kuang.pojo.UserT"> <constructor-arg type="java.lang.String" value="kuangshen2"/> </bean>
-
使用其他工厂或者其他类作用第三方创建bean对象
<bean id="beanFactory" class="com.com.wql.factory.BeanFactory"/> <bean id="accountService" factory-bean="beanFactory" factory-method="getFactory"/>
-
静态方法创建
<bean id="accountService" class="com.wql.factory.StaticFactory" factory-method="getBean" />
4、spring中的配置
4.1、设置别名:alias
<!--设置别名:在获取Bean的时候可以使用别名获取-->
<alias name="userT" alias="userNew"/>
<!--bean就是java对象,由Spring创建和管理-->
<!--
id 是bean的标识符,要唯一,如果没有配置id,name就是默认标识符
如果配置id,又配置了name,那么name是别名
name可以设置多个别名,可以用逗号,分号,空格隔开
如果不配置id和name,可以根据applicationContext.getBean(.class)获取对象;
class是bean的全限定名=包名+类名
-->
<bean id="hello" name="hello2 h2,h3;h4" class="com.kuang.pojo.Hello">
<property name="name" value="Spring"/>
</bean>
4.2、import
<import resource="{path}/beans.xml"/>
4.3、属性
<!--bean中的scope属性:
singleton:单例
prototype:多例
request:请求的作用范围
session:一次会话范围的范围
global-session:全局的会话范围(当在多台服务器中时)
-->
5、依赖注入(Dependency Injection)
5.1、依赖注入概念
-
依赖注入:ioc减少程序间的依赖关系,将依赖关系的具体管理交给spring; spring对程序见依赖关系的维护就叫依赖注入
-
依赖:指bean对象的创建依赖于容器,Bean对象的依赖资源
-
注入:指Bean对象所依赖的资源由容器所指定以及装配
-
注入类型:基本类型 配置的bean或使用注解的bean对象,复杂类型:集合
5.2、依赖注入的方式
***5.2.1、set***方法注入:
要求所注入的Bean对象必须拥有set方法,方法名由set+属性名首字母大写组成
public class AccountServiceImpl implements IAccountService {
private String name;
private Integer age;
private Date birthday;
public void setName(String name) {
this.name = name;
}
public void setAge(Integer age) {
this.age = age;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
<bean id="accountService2" class="com.com.wql.service.impl.AccountServiceImpl">
<!--name:为set方法后的属性名小写,value:为注入的属性所对应的值
相当于赋值的过程
-->
<property name="name" value="ggg"/>
<property name