spring
提高开发效率 运行效率
代码格式改变
spring 是一个轻量级的开源的 ioc/aop容器,目的是为了提高开发效率,降低层与层之间的耦合,实现层与层之间的分离
轻量级:
消耗的资源少(运行内存,cpu,IO)
框架的侵入程度(自身的代码不需要继承或者实现框架中的接口)
独立的实现,不需要依赖其他框架
开发的复杂程度(简单)
轻量级使用与中小型企业(重量级使用与大型企业,高可用性,高伸缩性)
IOC :控制反转(Inversion of control)
创建对象权限的反向转移
正常情况下:谁用谁创建
反转: 将创建对象的权限交给spring 容器,由容器统一创建对象,我们使用时,只需要从容器中获取对象即可.
applicationContext.xml
<!--
类的对象
id:对象名字 唯一,不能使用特殊字符
name:对象名字
class:类的全限定名 包名.类名
-->
<bean id="provincesId" class="com.lanou.pojo.Provinces"></bean>
简单使用
原有模式 通过类创建对象
通过spring创建对象
-
引入jar包
commons-logging-***.jar spring-context-***.jar spring-context-support-***.jar
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.1.3.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>5.1.3.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/commons-logging/commons-logging --> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.2</version> </dependency>
2。创建spring配置文件 applicationContext.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="provincesId" class="com.lanou.pojo.Provinces"></bean>
</beans>
3.测试
public class Test {
/*
原有模式,通过类创建类的对象 自己new
Provinces -- 类
p ---- 对象
*/
@org.junit.Test
public void createObject(){
Provinces p = new Provinces();
p.setId(1);
p.setProvinceid("410000");
p.setProvince("河南省");
System.out.println(p.toString());
}
/*
通过spring配置文件创建类的对象
*/
@org.junit.Test
public void createSpringObject(){
//加载spring配置文件
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//获取指定的bean对象
//1.通过bean的id获取
Provinces provinces = (Provinces) context.getBean("provincesId");
//2.通过bean的name获取
Provinces provinces1 = (Provinces) context.getBean("provincesName");
//3.通过类型获取,通过类型获取 不需要强转 不能保证唯一
Provinces provinces2 = context.getBean(Provinces.class);
//4.同时通过名称(id或name)和类型获取 既能保证唯一 又不用进行强转
Provinces provinces3 =context.getBean("provinces",Provinces.class);
provinces.setId(2);
provinces.setProvinceid("110000");
provinces.setProvince("北京");
System.out.println(provinces.toString());
}
}
applicationContext.xml配置文件
<!--
init-method="" 初始化方法
destroy-method="" 销毁对象之前执行的方法
scope: 作用域范围
scope="singleton" 单例
不管如何创建 都只能是一个对象
scope="prototype" 多例
创建一次是一个新的对象
lazy-init="true" 是否延时加载对象(只在单例模式下有效,在多例模式下每次都需要调用无参构造方法 所以无效)
1.立即加载 加载当前spring配置文件时就创建对象
2.延时加载 当第一次调用对象时加载
-->
<bean id="provinces" name="provincesName" class="com.xpc.pojo.Provinces"
init-method="init"
destroy-method="destory"
scope="singleton"
lazy-init="true"
></bean>
创建对象的方式
无参构造函数(默认)
<bean id="provinces" name="provincesName" class="com.xpc.pojo.Provinces"
init-method="init"
destroy-method="destory"
scope="singleton"
lazy-init="true"
></bean>
有参构造函数
静态工厂创建对象
创建工厂类 创建静态方法返回对象
public class ProvincesFactory {
/*静态工厂方法*/
public static Provinces create(){
return new Provinces();
}
}
在applicationContext.xml文件中创建
<!--工厂类对象-->
<bean id="provincesFactory" class="com.xpc.pojo.ProvincesFactory"
factory-method="create"
>
</bean>
测试
/*工厂方法创建对象*/
@Test
public void factory(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Provinces provinces = context.getBean("provincesFactory",Provinces.class);
}
非静态工厂方法创建对象
创建工厂类 创建非静态方法返回对象
public class ProvincesFactory {
/*静态工厂方法*/
public static Provinces create(){
System.out.println("静");
return new Provinces();
}
/*非静态工厂方法*/
public Provinces create1(){
System.out.println("非静");
return new Provinces();
}
}
配置文件
<bean id="provincesFactory" class="com.xpc.pojo.ProvincesFactory"
>
</bean>
<!--非静态工厂-->
<bean id="provincesFactory2" factory-bean="provincesFactory" factory-method="create1"
></bean>
测试
/*非静态工厂创建对象*/
@Test
public void factory2(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Provinces provinces = context.getBean("provincesFactory2",Provinces.class);
}
DI:依赖注入
对象的属性值依赖容器注入
简单使用
service层
public interface ProvincesService {
public void getProvinces();
}
实现类
public class ProvincesServiceImpl implements ProvincesService {
@Override
public void getProvinces() {
System.out.println("===serviceImpl===");
}
servlet调用service层方法
public class ProvincesServlet {
private int id;
private ProvincesService provincesService;
public void getProvinces(){
provincesService.getProvinces();
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public ProvincesService getProvincesService() {
return provincesService;
}
public void setProvincesService(ProvincesService provincesService) {
this.provincesService = provincesService;
}
applicationContext.xml文件配置
!--di依赖注入-->
<bean id="provincesService" class="com.xpc.service.impl.ProvincesServiceImpl">
</bean>
<bean id="provincesServlet" class="com.xpc.servlet.ProvincesServlet">
<!--简单类型 value注入-->
<property name="id" value="110"></property>
<!--自定义引用类型 ref参考注入-->
<property name="provincesService" ref="provincesService"></property>
</bean>
测试
@Test
public void testDI(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
ProvincesServlet provincesServlet = context.getBean(ProvincesServlet.class);
provincesServlet.getProvinces();
}
简单类型依赖注入
无参构造
<bean id="user" class="com.xpc.pojo.User">
<!--无参构造+setter方法-->
<property name="id" value="110"></property>
<property name="username" value="交警"></property>
<property name="password" value="001"></property>
</bean>
有参构造
<bean id="user" class="com.xpc.pojo.User">
<!--有参构造方法给对象属性赋值-->
<!--通过name属性给属性赋值-->
<constructor-arg name="id" value="119"></constructor-arg>
<constructor-arg name="username" value="刑警"></constructor-arg>
<constructor-arg name="password" value="100"></constructor-arg>
<!--利用索引赋值 但是一定要和实体类中的对应-->
<constructor-arg index="0" value="119"></constructor-arg>
<constructor-arg index="1" value="刑警"></constructor-arg>
<constructor-arg index="2" value="100"></constructor-arg>
<!--通过type注入-->
<constructor-arg name="id" value="119" type="int"></constructor-arg>
<constructor-arg name="username" value="刑警" type="java.lang.String"></constructor-arg>
<constructor-arg name="password" value="100" type="java.lang.String"></constructor-arg>
</bean>
复杂类型依赖注入
/*给复杂数据类型给属性赋值*/
public class TestCollection {
private User user;
private Object[] array;
private List<Object> list;
private Map<String,Object> map;
private Properties properties;
applicationContext.xml配置文件
<bean id="testCollection" class="com.xpc.pojo.TestCollection">
<!--对象类型 ref引入参照对象-->
<property name="user" ref="user"></property>
<!--数组-->
<property name="array">
<list>
<value>北京</value>
<value>上海</value>
<ref bean="user"></ref>
</list>
</property>
<!--集合类型-->
<property name="list">
<list>
<value>郑州</value>
<value>洛阳</value>
<value>开封</value>
</list>
</property>
<!--map-->
<property name="map">
<map>
<entry key="area" value="郑州"></entry>
<entry key="addr" value="洛阳"></entry>
<entry key="user" value-ref="user"></entry>
</map>
</property>
<!--给peoperties这样的属性赋值 key=value-->
<property name="properties">
<props>
<prop key="driver">com.mysql.jdbc.Driver</prop>
</props>
</property>
</bean>
AOP:面向切面
弥补面向对象编程的不足,
切面: 日志切面 ,事务切面,业务切面
切面类:切面方法
前置通知(方法调用之前执行)
后置通知(1.无论是否正常都执行 2.方法成功之后执行的内容)
环绕通知
异常通知
jar包支持
aop//已包含 可以不引入
spring-aspects
aoplliance
aspectjweaver//已包含 可以不引入
创建切面类 切面方法
public class LogAdvice {
/*
* 日志切面类
* 前置通知方法
* */
public void before(){
System.out.println("前置通知");
}
/*
* 后置通知
* */
public void after(){
System.out.println("后置通知");
}
/*
* 异常通知
* */
public void excpetion(){
System.out.println("异常通知");
}
/*
* 环绕通知
* */
public Object round(ProceedingJoinPoint point) throws Throwable {
//调用执行前
System.out.println("环绕前通知");
Object obj = point.proceed();//继续调用目标方法
//调用方法之后执行
System.out.println("环绕后通知");
return obj;
}
}
applicationConext.xml配置文件
<!--定义切面bean-->
<bean id="logAdvice" class="com.xpc.util.LogAdvice"></bean>
<!--定义日志切面-->
<aop:config>
<!--切入点信息
id: 名称
expression:表达式 找到 包,类,方法
第一个* :方法的返回值类型
com.xpc.service 切入的包名
第二个 * : 类名
第三个 * :方法名
(..) :任意参数
-->
<aop:pointcut id="pc" expression="execution(* com.xpc.service.*.*(..))"></aop:pointcut>
<!--定义切面和切入点的关联
ref: 指向切面
-->
<aop:aspect ref="logAdvice">
<!--切入方法 切入点-->
<!--前置通知-->
<aop:before method="before" pointcut-ref="pc"></aop:before>
<!--不管是否异常都会执行-->
<aop:after method="after" pointcut-ref="pc"></aop:after>
<!--后置通知无异常才会通知-->
<aop:after-returning method="after" pointcut-ref="pc"></aop:after-returning>
<!--异常通知-->
<aop:after-throwing method="excpetion" pointcut-ref="pc"></aop:after-throwing>
<!--环绕通知-->
<aop:around method="round" pointcut-ref="pc"></aop:around>
</aop:aspect>
</aop:config>