网站建设 杭州,上海专业页面设计模型设计,工信部的网站备案信息查询,东莞vi设计一、spring概述 1.1 spring介绍
spring是一个轻量级的控制反转和面向切面的容器框架#xff0c;用来解决企业项目开发的复杂度问题---解耦
轻量级#xff1a;体积小#xff0c;对代码没有侵入性控制反转#xff1a;IOC inverse of control#xff0c; 把创建对象的工作交…一、spring概述 1.1 spring介绍
spring是一个轻量级的控制反转和面向切面的容器框架用来解决企业项目开发的复杂度问题---解耦
轻量级体积小对代码没有侵入性控制反转IOC inverse of control 把创建对象的工作交由spring完成spring在创建对象的同时可以完成对象属性的赋值DI面向切面AOP aspect oriented programming 面向切面编程可以在不改变原有业务逻辑的情况下实现对业务的增强容器实例的容器管理创建的对象
1.2 spring架构简介 1.2.1 core container
spring的容器组件用于完成实例的创建和管理
core 容器组件的核心beans 实例对象的管理context 容器上下文
1.2.2 AOP Aspects
spring的AOP组件实现面向切面编程
aop aspects
1.2.3 WEB
Spring web组件实际指的是springMVC框架实现web项目的MVC控制
web ---spring 对web项目的支持webmvc --- springMVC
1.2.4 Data Access
spring 数据访问组件也是一个基于JDBC封装的持久层框架即使没有mybatisspring也可以完成持久化操作
transactions 事务管理
1.2.5 test
spring的单元测试组件提供了spring环境下的单元测试支持。 二、Spring IOC --- 基于XML
spring ioc 容器组件可以完成对象的创建对象属性赋值对象的管理
2.1 spring框架部署IOC相关
创建maven工程添加springIOC依赖 corebeanscontext --- 其实只导入这一个就行了因为其他的依赖也会一起导入创建spring配置文件 配置文件来“告诉”spring容器创建什么对象给对象属性怎么赋值resources目录下创建名为applicationContext.xml文件文件名可以自定义需要定义一些规则可以创建一个模板
spring 依赖
!--
dependencygroupIdorg.springframework/groupIdartifactIdspring-core/artifactIdversion5.2.10.RELEASE/version
/dependency
dependencygroupIdorg.springframework/groupIdartifactIdspring-beans/artifactIdversion5.2.10.RELEASE/version
/dependency
--
dependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdversion5.2.10.RELEASE/version
/dependency 2.2 springIOC的使用 创建并管理对象
创建do实体类如Student类applicationContext.xml文件中配置bean标签初始化spring容器加载spring配置文件获取实例对象
只完成实例的创建但是属性没有值
bean idstudentDo唯一标识 namedao classStudent的全限定名/完成实例的创建同时给name属性赋值
bean idstudentDo唯一标识 namedao classStudent的全限定名property namestuName valuezhangsan /
/bean public static void main(String[] args) {ApplicationContext ctx new ClassPathXmlApplicationContext(applicationContext.xml);//此处根据bean标签的id属性和name属性的任意一个值来获取bean对象// 创建出来student对象但是属性没有值Student Student1 (Student) ctx.getBean(studentDo);
} 2.3 IOC和DI
IOC inverse of control控制反转当我们需要通过spring完成对象的创建时需要将这个类交给spring进行管理 ---- 通过配置bean标签spring反射DI dependency injection 依赖注入通过spring容器给创建的对象属性赋值
2.4 DI
2.4.1 依赖注入的方式 --- 反射
spring容器加载配置文件后通过反射创建类的对象并给属性赋值。通过反射实现属性注入有以下几种方式
set方法注入构造器注入接口注入不常用。。。
2.4.2 set注入
在bean标签中通过配置property标签给属性赋值实际就是通过set方法进行注入
简单类型及字符串 ---- 直接通过property标签的value属性进行赋值引用类型 ---- 使用property标签ref属性注入引用类型对象---- 在property标签里面创建bean标签集合类型 list list简单类型封装类或者字符串 可以在property 的value里面直接赋值 逗号隔开list引用类型 见下面set ---和list一样就是把list标签变成setmap
bean idbookService classcom.itheima.service.impl.BookServiceImplproperty namebookDao refbookDao/
/bean
bean idbookDao classcom.itheima.dao.imipl.BookDaoImpl/-------bean idbookService classcom.itheima.service.impl.BookServiceImplproperty namebookDaobean idbookDao classcom.itheima.dao.imipl.BookDaoImpl//property
/bean--------
list 依赖注入1
property namehobbies value唱,跳,rap---------
list 依赖注入2
property namehobbieslistvalue唱/valuevalue跳/valuevaluerap/value/list
/property---------
list 依赖注入3property namehobbieslistbean idbook classcom.itheima.Book/bean idbook classcom.itheima.Book/bean idbook classcom.itheima.Book//list
/property---------
list 依赖注入4property namehobbieslistref idbook/ref idbook//list
/propertybean idbook classcom.itheima.Book/---------
mapproperty namecardmapentry key身份证 value123712739171293/entryentry key银行卡 value234234234324344/entry/map
/property
2.4.3 构造器注入
简单类型和字符串 1、定义有参构造器2、使用constructor-arg标签index值为第几个参数value为要注入的值对象类型集合类型
bean idbookDao classcom.itheima.dao.impl.BookDaoImplconstructor-arg namedatabaseName index0 valuemysql/constructor-arg nameconnectionNum index1 value666/
/beanbean idbookService classcom.itheima.service.impl.BookServiceImplconstructor-arg namebookDao refbookDao/constructor-arg nameuserDao refuserDao/
/bean 2.5 ioc- bean的作用域
同一个bean_id 通过配置scope 的值来指定对象的作用域
singleton ---单例模式 默认的值默认饿汉模式初始化阶段就会完成实例的创建prototype ---多例模式
bean idbook classbook的全限定名 scope lazy-init/
scope 有两个取值
singleton ---单例模式 默认的
prototype ---多例模式lazy-init默认取值false饿汉模式设置为true可以改为懒汉模式 2.6 bean 的生命周期
bean标签中可以
通过init-method属性指定当前bean的初始化方法在构造器执行之后执行通过destroy-method指定当前bean的销毁方法在对象销毁之前执行2.7 自动装配
spring在实例化当前bean时重spring自己的容器中找到匹配的实例赋值给当前bean的属性通过bean标签中的autowire进行配置
byName根据当前bean的属性名 在spring容器中寻找名称匹配的对象bean中的属性名称和spring容器中其他bean的id 进行比较有可能导致类型不一致byType根据当前bean的属性类型在spring容器中寻找类型匹配的对象 要是配置了两个不同id的bean也会报错
2.8 ioc的工作原理 三、Spring IOC --- 基于注解
3.1 spring框架部署
3.1.1 创建maven项目
3.1.2添加springIOC依赖
dependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdversion5.2.13.RELEASE/version
/dependency
3.1.3 创建spring配置文件声明spring的扫描范围
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd!-- 声明使用注解配置 --context:annotation-config/!-- 声明Spring工厂注解的扫描范围 --context:component-scan base-packagecom.qfedu.beans//beans
3.2 IOC的常见注解
3.2.1 Component
类注解声明此类被spring容器进行管理相当于bean标签Componentvalue“stu”value属性的值相当于bean标签中的id可以省略如果省略则当前类的id默认为类名首字母改小写除了Component Service、Controller、Repository这三个注解也可以将类声明给Spring管理他们主要是语义上的区别 Controller 注解主要声明将控制器类配置给Spring管理例如ServletService 注解主要声明业务处理类配置Spring管理Service接口的实现类Repository 直接主要声明持久化类配置给Spring管理DAO接口
3.2.2 Scope
类注解用于声明当前类是否是单例模式相当于bean标签的scope属性Scope(prototype) 表示声明当前类为非单例模式默认单例模式
3.2.3 Lazy
类注解用于声明一个单例bean是否为懒汉模式默认为饿汉模式Lazy(true) 表示声明为懒汉模式
3.2.4 PostConstruct
方法注解声明一个方法为当前类的初始化方法在构造器之后执行相当于bean标签的init-method属性
3.2.5 PreDestory
方法注解声明一个方法为当前类的销毁方法在对象从容器中释放之前执行相当于bean标签的destory-method属性
3.2.6 Autowoired
属性注解声明当前属性自动装配默认为byTypeAutowired(required false) 通过requried属性设置当前自动装配是否为必须默认必须——如果没有找到类型与属性类型匹配的bean则抛出异常
// 也可以用在set方法上ref引用Qualifier来byName寻找
Autowired
public void setClazz(Qualifier(c2) Clazz clazz) {this.clazz clazz;
}
3.2.7 Resource 属性注解也用于声明属性自动装配 默认装配方式为byName如果根据byName没有找到对应的bean则继续根据byType寻找对应的bean根据byType如果依然没有找到Bean或者找到不止一个类型匹配的bean,则抛出异常。 四动态代理
代理设计模式的优点将通用性的工作都交给代理对象完成被代理对象只需专注自己的核心业务。
动态代理几乎可以为所有的类产生代理对象
4.1 JDK动态代理类实现
JDK动态代理是通过被代理类实现的接口来创建代理对象的因此JDK动态代理只能代理实现了接口的类的对象。没有实现接口的类是不能用这种方式产生代理对象。
//使用代理对象调用方法并不会执行调用的方法 //而是进入到创建代理对象时指定的InvocationHandler类种的invoke方法调用的方法作为一个Method参数传递给了invoke方法
/**** JDK动态代理是通过被代理对象实现的接口产生其代理对象的* 1.创建一个类实现InvocationHandler接口重写invoke方法* 2.在类种定义一个Object类型的变量并提供这个变量的有参构造器用于将被代理对象传递进来* 3.定义getProxy方法用于创建并返回代理对象*/
public class JDKDynamicProxy implements InvocationHandler {//被代理对象private Object obj;public JDKDynamicProxy(Object obj) {this.obj obj;}//产生代理对象返回代理对象public Object getProxy(){//1.获取被代理对象的类加载器ClassLoader classLoader obj.getClass().getClassLoader();//2.获取被代理对象的类实现的接口Class?[] interfaces obj.getClass().getInterfaces();//3.产生代理对象(通过被代理对象的类加载器及实现的接口)//第一个参数被代理对象的类加载器//第二个参数被代理对象实现的接口//第三个参数使用产生代理对象调用方法时用于拦截方法执行的处理器Object proxy Proxy.newProxyInstance(classLoader, interfaces,this);return proxy;}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {begin();Object returnValue method.invoke(obj,args); //执行method方法insertcommit();return returnValue;}public void begin(){System.out.println(----------开启事务);}public void commit(){System.out.println(----------提交事务);}
}// --------------测试------------------//创建被代理对象
BookDAOImpl bookDAO new BookDAOImpl();
StudentDAOImpl studentDAO new StudentDAOImpl();//创建动态代理类对象并将被代理对象传递到代理类中赋值给obj
JDKDynamicProxy jdkDynamicProxy new JDKDynamicProxy(studentDAO);//proxy就是产生的代理对象:产生的代理对象可以强转成被代理对象实现的接口类型
GenaralDAO proxy (GenaralDAO)jdkDynamicProxy.getProxy();//使用代理对象调用方法并不会执行调用的方法
//而是进入到创建代理对象时指定的InvocationHandler类种的invoke方法
//调用的方法作为一个Method参数传递给了invoke方法
proxy.insert(student);
4.2 CGLib动态代理实现
CGLib动态代理是通过创建被代理类的子类来创建代理对象的因此即使没有实现任何接口的类也可以通过CGLib产生代理对象
因为是创建子类因此CGLib动态代理不能为final类创建代理对象
添加CGLib的依赖
!-- https://mvnrepository.com/artifact/cglib/cglib --
dependencygroupIdcglib/groupIdartifactIdcglib/artifactIdversion3.3.0/version
/dependency
/*** 1.添加cglib依赖* 2.创建一个类实现MethodInterceptor接口同时实现接口中的intercept方法* 3.在类中定义一个Object类型的变量并提供这个变量的有参构造器用于传递被代理对象* 4.定义getProxy方法创建并返回代理对象代理对象是通过创建被代理类的子类来创建的*/
public class CGLibDynamicProxy implements MethodInterceptor {private Object obj;public CGLibDynamicProxy(Object obj) {this.obj obj;}public Object getProxy(){Enhancer enhancer new Enhancer();enhancer.setSuperclass(obj.getClass());enhancer.setCallback(this);Object proxy enhancer.create();return proxy;}public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {begin();Object returnValue method.invoke(obj,objects); //通过反射调用被代理类的方法commit();return returnValue;}public void begin(){System.out.println(----------开启事务);}public void commit(){System.out.println(----------提交事务);}
}// ------------测试 ------------//创建被代理对象
BookDAOImpl bookDAO new BookDAOImpl();
StudentDAOImpl studentDAO new StudentDAOImpl();//通过cglib动态代理类创建代理对象
CGLibDynamicProxy cgLibDynamicProxy new CGLibDynamicProxy(bookDAO);
//代理对象实际上是被代理对象子类因此代理对象可直接强转为被代理类类型
BookDAOImpl proxy (BookDAOImpl) cgLibDynamicProxy.getProxy();//使用对象调用方法实际上并没有执行这个方法而是执行了代理类中的intercept方法将当前调用的方法以及方法中的参数传递到intercept方法
proxy.update(); 五、Spring AOP
5.1 AOP的概念
aspect oriented programming 面向切面编程是一种利用横切的技术对原有的业务逻辑进行拦截并且可以在这个拦截的横切面上添加特点的业务逻辑实现不改变代码对原有业务的增强。
底层的实现就是动态代理。
连接点 joinPoint原始程序中的方法
切入点pointCut被spring横切的方法
通知/增强
切点添加到切入点的 新增的业务方法
切面定义切点方法的类 5.2 Spring AOP 框架部署
5.2.1 创建maven项目
5.2.2 添加依赖
dependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdversion5.2.13.RELEASE/version
/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-aspects/artifactIdversion5.2.13.RELEASE/version
/dependency
5.3 AOP配置 --基于xml
例子在DAO方法中添加开启事务和提交事务的逻辑
5.3.1 创建一个类定义要添加的业务逻辑 --- 这个类就是切面里面定义的方法就是切点
public class TxManager {public void begin(){System.out.println(-----------开启事务);}public void commit(){System.out.println(-----------提交事务);}
}
5.3.2 配置AOP
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:aophttp://www.springframework.org/schema/aopxsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdbean idbookDAO classcom.qfedu.dao.BookDAOImpl/beanbean idstudentDAO classcom.qfedu.dao.StudentDAOImpl/bean!----bean idtxManager classcom.qfedu.utils.TxManager/beanaop:config!--声明切入点--aop:pointcut idbook_all expressionexecution(* com.qfedu.dao.*.*(..))/!--声明txManager为切面类--aop:aspect reftxManager!--通知--aop:before methodbegin pointcut-refbook_all/aop:after methodcommit pointcut-refbook_all//aop:aspect/aop:config/beans
总结AOP的开发步骤
创建一个切面类定义切点方法将切面类配置给spring容器声明切入点配置AOP的通知策略
5.4 切入点的声明
5.4.1 各种切入点声明方式
!--使用aop:pointcut标签声明切入点切入点可以是一个方法--
aop:pointcut idbook_insert expressionexecution(* com.qfedu.dao.BookDAOImpl.insert())/!--BookDAOImpl类中所有无参数无返回值的方法--
aop:pointcut idbook_pc1 expressionexecution(void com.qfedu.dao.BookDAOImpl.*())/!--BookDAOImpl类中所有无返回值的方法--
aop:pointcut idbook_pc2 expressionexecution(void com.qfedu.dao.BookDAOImpl.*(..))/!--BookDAOImpl类中所有无参数的方法--
aop:pointcut idbook_pc3 expressionexecution(* com.qfedu.dao.BookDAOImpl.*())/!--BookDAOImpl类中所有方法--
aop:pointcut idbook_pc4 expressionexecution(* com.qfedu.dao.BookDAOImpl.*(..))/!--dao包中所有类中的所有方法--
aop:pointcut idpc5 expressionexecution(* com.qfedu.dao.*.*(..))/!--dao包中所有类中的insert方法--
aop:pointcut idpc6 expressionexecution(* com.qfedu.dao.*.insert(..))/
5.4.2 AOP使用的注意事项
如果要使用spring aop 面向切面编程调用切入点方法的对象必须是通过spring容器获取的。
如果一个类中的方法被声明为切入点并织入了切点之后通过spring容器获取该类对象实际获取到的是一个代理对象
如果一个类中的方法没有被声明为切入点通过spring容器获取的就是这个类真实的对象。
//BookServiceImpl bookService new BookServiceImpl();
BookServiceImpl bookService (BookServiceImpl) context.getBean(bookServiceImpl);
bookService.addBook();
5.5 AOP的通知策略
AOP的通知策略就是声明将切面类中的切点方法 如何织入到切入点
before -- 前置通知after -- 后置 通知after-throwing -- 异常之后的通知after-returning -- 方法返回值之后与 after的时机属于一个时间点看那个先配置就先执行那个around -- 环绕通知定义环绕通知的切点方法要遵守特定的规则
bean idmyAspect classcom.qfedu.utils.MyAspect/bean
aop:config!--使用aop:pointcut标签声明切入点切入点可以是一个方法--aop:pointcut idbook_insert expressionexecution(* com.qfedu.dao.BookDAOImpl.insert())/aop:aspect refmyAspect!--aop:before 前置通知切入到指定切入点之前--aop:before methodmethod1 pointcut-refbook_insert/!--aop:after 后置通知切入到指定切入点之后--aop:after methodmethod2 pointcut-refbook_insert/!--aop:after-throwing 异常通知切入点抛出异常之后--aop:after-throwing methodmethod3 pointcut-refbook_insert/!--aop:after-returning 方法返回值返回之后对于一个Java方法而言return返回值也是方法的一部分因此“方法返回值返回之后”和“方法执行结束”是同一个时间点随意after 和 after-returning根据配置的顺序决定执行顺序--aop:after-returning methodmethod4 pointcut-refbook_insert/aop:around methodmethod5 pointcut-refbook_insert//aop:aspect/aop:config
public class MyAspect {public void method1(){System.out.println(~~~~~~~method1);}public void method2(){System.out.println(~~~~~~~method2);}public void method3(){System.out.println(~~~~~~~method3);}public void method4(){System.out.println(~~~~~~~method4);}//环绕通知的切点方法必须准守如下的定义规则//1.必须带有一个ProceedingJoinPoint类型的参数//2.必须有Object类型的返回值//3.在前后增强的业务逻辑之间执行Object v point.proceed();//4.方法最后返回vpublic Object method5(ProceedingJoinPoint point) throws Throwable {System.out.println(~~~~~~~method5---before);//此代码的执行就表示切入点方法的执行Object v point.proceed();System.out.println(~~~~~~~method5---after);return v;}}