一、Spring介绍

Spring 是位于业务逻辑层的框架。 优点很多(无缝对接前后层的框架、提供AOP的支持 , 和以前的 Sstruts 、 Hibernate 组合成了一套框架组合 SSH 。现在是和Spring MVC 、 MyBatis 成了新的组合 SSM) 。 spring里面包含两个核心 : IOC + AOP

  • IOC

IOC 的全称是 Inversion Of Control 翻译过来是控制反转的意思。 通俗的说: 就是把对象的创建工作交给spring来完成。

  1. 以前创建对象 new 类(); ----> 把工作交给spring ----> spring要对象即可
  • AOP

AOP为Aspect Oriented Programming的缩写,意为:面向切面编程

二、IOC演变

创建对象的发展历史

  • 早期直接new对象

  • 演变成工厂

  • spring ioc托管

三、Spring入门

1. 入门案例

  1. 添加依赖
  1. compile 'org.springframework:spring-context:4.3.17.RELEASE'
  1. 编写业务逻辑类
  1. public interface UserService {
  2. void save();
  3. }
  4. public class UserServiceImpl implements UserService {
  5. @Override
  6. public void save() {
  7. System.out.println("调用UserServiceImpl的save方法~~");
  8. }
  9. }
  1. 创建配置文件 applicationContext.xml
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
  5. <bean id="userService" class="com.itheima.service.impl.UserServiceImpl"/>
  6. </beans>
  1. 在代码里面通过工厂获取对象
  1. public class MainTest {
  2. @Test
  3. public void testSave(){
  4. ClassPathXmlApplicationContext context = new
  5. ClassPathXmlApplicationContext("applicationContext.xml");
  6. UserService userService = (UserService) context.getBean("userService");
  7. userService.save();
  8. context.close();
  9. }
  10. }

2. 配置详解

1. xml解释

  1. <!-- bean标签用来托管具体类,也就是告诉spring工厂,我们让它帮忙创建谁的实例对象
  2. id | name: 唯一标识符,不建议写一样的内容
  3. class : 全路径
  4. 默认创建的实例是单例.
  5. 如果想要做成多例,那么请使用scope属性,里面给值prototype ,
  6. 默认是单例 ==== singleton
  7. -->
  8. <bean id="us" class="com.itheima.service.impl.UserServiceImpl" scope="prototype"></bean>

2. 代码解释

  1. //2. 让spring创建对象 问spring的工厂要对象
  2. //创建工厂,然后告诉工厂,配置文件在哪里。 工厂就会解析这个xml文件,进而得出us --- UserServiceImpl的对应关系
  3. ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
  4. //问工厂要对象
  5. UserService userService =(UserService) context.getBean("us");
  6. userService.save();
  7. //关闭工厂,一般不会调用这个方法。
  8. ((AbstractApplicationContext) context).close();

四、IOC

此处使用两种方式给大家介绍, xml注解方式

1. xml方式

  • 代码:
  1. public class UserServiceImpl implements UserService {
  2. @Override
  3. public void save() {
  4. System.out.println("调用UserServiceImpl的save方法~~");
  5. }
  6. }
  • xml配置
  1. <bean id="us" class="com.itheima.service.impl.UserServiceImpl"></bean>

2. 注解方式

即便使用注解,也还是需要在配置文件里面声明注解的开关

  • 代码
  1. @Compoment
  2. public class UserServiceImpl implements UserService {
  3. @Override
  4. public void save() {
  5. System.out.println("调用UserServiceImpl的save方法~~");
  6. }
  7. }
  • xml配置
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
  6. <!-- 打开扫描开关 -->
  7. <context:component-scan base-package="com.itheima"/>
  8. </beans>
  • 细节
  1. 为了迎合三层结构的趋势,Spring 为每一个层级制定了各自的注解,

​ controller层使用 @Controller

​ service层使用@Service

​ dao层使用@Repository

  1. 如果需要给指定的bean添加标识,可以使用注解属性追加 如: @service("userService")

  2. 默认情况下生成的实例还是单例,如果需要做成多例,需要额外加上 @Scope("prototype")

五、依赖注入

DI : 全称是 dependency Injection 翻译过来是依赖注入 本意是在实例化对象的时候,对它里面的成员属性进行值的注入。

public class UserServiceImpl{

​ private String address;

}

对这个address进行赋值: 有几种方式: 两种

  1. 有参构造

  2. set方法

    依赖注入,走的就是上面的这两种。 如果使用注解注入,使用的是反射。

1. xml方式

xml方式需要在配置文件中配置,以完成值的注入,提供两种方法, 有参构造和set方法。

a. 有参构造

  • 代码
  1. public class UserServiceImpl implements UserService {
  2. private String address;
  3. //必须走有参构造
  4. public UserServiceImpl(String address) {
  5. this.address = address;
  6. }
  7. @Override
  8. public void save() {
  9. System.out.println("调用UserServiceImpl的save方法~~" + address);
  10. }
  11. }
  • xml配置
  1. <bean id="us" class="com.itheima.service.impl.UserServiceImpl" >
  2. <!--
  3. constructor-arg : 一旦配置,就指定了spring的工厂走的是 有参构造。
  4. name:说的是属性名称
  5. value: 注入的值 -->
  6. <constructor-arg name="address" value="深圳"></constructor-arg>
  7. </bean>

b. set方法

  • 代码
  1. public class UserServiceImpl implements UserService {
  2. private String address;
  3. public void setAddress(String address) {
  4. this.address = address;
  5. }
  6. @Override
  7. public void save() {
  8. System.out.println("调用UserServiceImpl的save方法~~" + address);
  9. }
  10. }
  • xml配置
  1. <bean id="us" class="com.itheima.service.impl.UserServiceImpl" >
  2. <!-- property标签对应的是代码里面set方法
  3. name: 属性的名称
  4. value: 要注入的值 -->
  5. <property name="address" value="深圳"></property>
  6. </bean>

c. 注入集合类型

1. 数组

  1. 代码:
  2. private String [] address;
  3. public void setAddress(String [] address) {
  4. this.address = address;
  5. }
  6. xml:
  7. <property name="address">
  8. <array>
  9. <value>北京1</value>
  10. <value>北京2</value>
  11. <value>北京3</value>
  12. <value>北京天安门,我爱北京</value>
  13. </array>
  14. </property>

2. list

  1. 代码:
  2. private List address;
  3. public void setAddress(List address) {
  4. this.address = address;
  5. }
  6. xml:
  7. <property name="address">
  8. <list>
  9. <value>北京11</value>
  10. <value>北京22</value>
  11. <value>北京33</value>
  12. <value>北京天安门,我爱北京44</value>
  13. </list>
  14. </property>

3. map

  1. 代码:
  2. private Map<String , Object> address;
  3. public void setAddress(Map<String , Object> address) {
  4. this.address = address;
  5. }
  6. xml:
  7. <!-- map集合 -->
  8. <property name="address">
  9. <map>
  10. <entry key="地址1" value="北京1"/>
  11. <entry key="地址2" value="北京2"/>
  12. <entry key="地址3" value="北京3"/>
  13. <entry key="地址4" value="北京4"/>
  14. </map>
  15. </property>

d. 注入 对象类型

在某一个类当中,持有另一个类的引用,我们需要让spring创建这个类的引用,进而通过调用set方法来完成注入

  • 代码
  1. public class UserServiceImpl implements UserService {
  2. private UserDao userDao;// = new UserDaoImpl(); 体现了两层意思: a. new 某一个类的实例, b. 做出来的实例,赋值给dao.
  3. public void setUserDao(UserDao userDao) {
  4. this.userDao = userDao;
  5. }
  6. @Override
  7. public void save() {
  8. System.out.println("调用UserServiceImpl的save方法~~" );
  9. //UserDao userDao = new UserDaoImpl();
  10. userDao.save();
  11. }
  12. }
  • xml
  1. <!-- 让spring托管这个UserDaoImpl ,以便它能够创建该类的实例, 是为了完成下面的注入 -->
  2. <bean id="ud" class="com.itheima.dao.impl.UserDaoImpl"></bean>
  3. <bean id="us" class="com.itheima.service.impl.UserServiceImpl" >
  4. <!-- 指定了UserServiceImpl里面有一个属性叫做userDao ,它需要被注入, 注入的数据来自于 ref 里面声明的ud
  5. spring会拿着ud 找到对应的bean, 接着做出来实例,然后注入给userDao -->
  6. <property name="userDao" ref="ud"></property>
  7. </bean>

2. 注解方式

依赖注入使用注解来实现 , DI的注解一般使用两个 @Resource & @Autowired

  • 常用的注解就两个 @Resource & @Autowired

@Resource(name="ud") 根据给定的标记找到对应的类,创建对象,注入进来。

@Autowired 自动装配,会找到对应的实现类创建对象,注入进来。但是如果存在多个实现,那么会抛出异常

  1. @Repository("ud")
  2. public class UserDaoImpl implements UserDao {
  3. }
  4. public class UserServiceImpl implements UserService {
  5. @Resource(name="ud") //spring拿着ud找到具体的类,然后创建实例,注入进来。
  6. private UserDao userDao;
  7. ...
  8. }
  9. ----------------------------------------------------------
  10. public class UserServiceImpl implements UserService {
  11. @Autowired //自动装配 根据注入的接口类型找到对应的实现类,注入进来。
  12. private UserDao userDao;
  13. ...
  14. }

三、 AOP

1. 什么是AOP ? 它有什么用?

AOP(Aspect Oriented Programming,面向切面编程), 可以说是OOP(Object Oriented Programing,面向对象编程)的补充和完善。在不改动源码的前提下,对原有的功能进行扩展 | 升级

2. AOP的底层原理

在java的世界里,能够不改动源码,但是又能做出扩展|增强的,不多。有装饰者模式, 有代理模式(静态代理 + 动态代理。) aop的底层采用的是: 动态代理。之所以不用装饰者模式或者静态代理,那是因为这里两种方式,都需要我们写实实在在的扩展类(装饰类 + 代理类) 。

  • 代理回顾

3. 动态代理的实现方式

  • 基于JDK的方式

针对的是被代理类有实现某一个接口,底层创建接口的另一个实现类作为代理类

  1. //jdk动态代理
  2. @Test
  3. public void testJDKPorxy(){
  4. //UserService userService = new UserServiceImpl();
  5. //userService.save();
  6. //1. 先创建真实对象
  7. final UserService userService = new UserServiceImpl();
  8. //2. 创建代理对象
  9. UserService proxyObj = (UserService) Proxy.newProxyInstance(
  10. userService.getClass().getClassLoader(), //类加载器,真实类用什么,代理类就用什么
  11. userService.getClass().getInterfaces(), //真实类实现什么接口,代理类也实现什么接口
  12. new InvocationHandler() {//回调函数
  13. @Override
  14. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  15. System.out.println("invoke~");
  16. //userService.save();
  17. if(method.getName().equals("save")){
  18. Logger.log();
  19. }
  20. //以不变应万变。 反射调用
  21. return method.invoke(userService, args);
  22. }
  23. });
  24. //3. 让代理对象干活
  25. proxyObj.save(); //代理对象。save() ----> 真实对象.save();
  26. }
  • 基于Cglib动态代理

如果真实类是一个普通类,没有实现接口,那么就采用这种方式, 创建出来真实类的子类作为代理类。

  1. //cglib动态代理
  2. @Test
  3. public void testCglibPorxy(){
  4. //1. 一定要有真实对象
  5. final ProductService productService = new ProductService();
  6. //2. 创建代理
  7. Enhancer enhancer = new Enhancer();
  8. //设置父类是谁
  9. enhancer.setSuperclass(ProductService.class);
  10. //设置回调
  11. enhancer.setCallback(new MethodInterceptor() {
  12. /*
  13. * arg0 :代理对象
  14. * arg3 : 方法的代理
  15. *
  16. * 一般这两不用。
  17. *
  18. * arg1 : 方法引用
  19. * arg2 :参数
  20. */
  21. @Override
  22. public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
  23. Logger.log();
  24. return arg1.invoke(productService, arg2);
  25. }
  26. });
  27. //创建代理对象
  28. ProductService proxyObj = (ProductService) enhancer.create();
  29. proxyObj.save();
  30. }

3. AOP术语

4.AOP的入门

Spring的AOP其实已经准备好了创建代理的代码。只是不知道的是要创建谁的代码。哪些方法需要被增强。我们需要通过配置的形式告诉spring。

  1. 定义业务逻辑类
  1. public class UserServiceImpl implements UserService {
  2. @Override
  3. public void save() {
  4. System.out.println("调用了UserServiceImpl 的 save方法");
  5. }
  6. }
  1. 定义增强类
  1. public class Logger {
  2. public static void log(){
  3. System.out.println("输出日志了~~");
  4. }
  5. }
  1. 添加依赖
  1. compile 'org.springframework:spring-context:4.3.17.RELEASE'
  2. //aspectJ 依赖包。
  3. compile group: 'org.aspectj', name: 'aspectjweaver', version: '1.8.10'
  1. xml中配置

要导入aop的约束

  1. spring托管 业务逻辑类 增强类
  2. <bean id="us" class="com.itheima.service.impl.UserServiceImpl" ></bean>
  3. <bean id="logger" class="com.itheima.util.Logger" ></bean>
  4. 配置AOP
  5. <!-- 2. 开始配置aop -->
  6. <aop:config>
  7. <!-- 配置切入点 expression 表达式 '
  8. execution(* com.xyz.myapp.service.*.*(..))
  9. execution 固定写法
  10. 第一个* 代表任意返回值
  11. com.xyz.myapp.service : 包名
  12. 第二个* 包下的任意类
  13. 第三个* 类中的任意方法
  14. (..) : 任意参数
  15. saveUser
  16. saveOrder
  17. -->
  18. <aop:pointcut expression="execution(* com.itheima.service.impl.*.*(..))" id="aa"/>
  19. <!-- 配置增强
  20. 根据aa的表达式找到的方法,都给他们做前置增强,增强的功能是log方法
  21. -->
  22. <aop:aspect ref="logger">
  23. <aop:before method="log" pointcut-ref="aa"/>
  24. </aop:aspect>
  25. </aop:config>

5. AOP 增强

  1. <aop:config>
  2. <aop:pointcut expression="execution(* com.itheima.service.impl.*.*(..))" id="pointcut01"/>
  3. <!-- 以后去企业写代码,真正用aop来扩展一个功能,比较少。 除非是我们想扩展第三方jar包。
  4. aop的思想无处不在: struts 拦截器 (就是AOP) -->
  5. <!-- 配置切面aspect -->
  6. <aop:aspect ref="logger">
  7. <!-- 前置增强 -->
  8. <!-- <aop:before method="log" pointcut-ref="pointcut01"/> -->
  9. <!-- 最终增强 -->
  10. <!-- <aop:after method="log" pointcut-ref="pointcut01"/> -->
  11. <!-- 后置增强 -->
  12. <!-- <aop:after-returning method="log" pointcut-ref="pointcut01"/> -->
  13. <!-- 异常增强 -->
  14. <!-- <aop:after-throwing method="log" pointcut-ref="pointcut01"/> -->
  15. <!-- 环绕增强 -->
  16. <!-- <aop:around method="around" pointcut-ref="pointcut01"/> -->
  17. <aop:before method="log" pointcut-ref="pointcut01"/>
  18. <aop:after-returning method="log" pointcut-ref="pointcut01"/>
  19. </aop:aspect>
  20. </aop:config>

springboot10 framwork的更多相关文章

  1. 1.使用Entity Framwork框架常用的技术手段Code First 和Reverse Engineer Code First

    提示:VS版本2013,  Entity Framwork版本5.0.0,Mysql数据库  使用Entity FrameWork的好处就不多说,直接上手如何使用.两种形式:1.将代码映射到数据库实体 ...

  2. [读书笔记]C#学习笔记一: .Net Framwork

    前言: 一次偶然的机会  在园子里看到@Learning hard 出版的一本书: <<C#学习笔记>>, 然后买来 一直到现在读完, 感觉很不错, 适合入门, 书中内容是从C ...

  3. C#笔记一 .Net Framwork

    参考Learning hard本人在博客园的主页: http://www.cnblogs.com/zhili/     以及本书中的一些知识点: http://www.cnblogs.com/zhil ...

  4. 018如何建立自动化框架 how to bulid the framwork

    本讲包括: 一. objective 二. How to bulid 三. Keyview of frawork (关键视图) 四. conclusion automation framwork:自动 ...

  5. Entity Framwork db First 中 Model验证解决办法。

    由于项目中用到 Entity Framwork db First     每次从数据库生成数据模型之后都会把模型更新. 只要有一个表更新.所有的类都会重新生成. 在网上找了各种例子都是差不多的, 可能 ...

  6. 温故而知新之java的collection framwork

    经常用到的List,Map等这些数据结构,都是来自于java的util包下,而java对于其整体设计,简称为collection framwork.(ps.其实,Map接口并不继承自collectio ...

  7. rabbitmq支持.net framwork 3.5的最后版本

    方便后来人!!!经过一系列的确认!! rabbitmq支持.net framwork 3.5的最后版本是3.4.3, 安装步骤: 1.工具->Nuget程序包管理器,进入控制台 2.Instal ...

  8. REST framwork之分页器,路由器,响应器

    一 REST framwork分页器: from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination ...

  9. 记录一次BUG修复-Entity Framwork SaveChanges()失效

    目录 一. 前言 二.问题背景 三.问题描述 四.问题解决步骤 六.总结 一. 前言 这是笔者在参与一个小型项目开发时所遇到的一个BUG,因为项目经验不足对Entity Framwork框架认识不足导 ...

随机推荐

  1. Math.random()随机生成x~y间的数字

    JS如何随机产生数字呢?这就用到了Math.random()方法,它能够随机产生0~1间的数字,这个数可能为0,但会小于1. 那么,如果我想要大于等于1小于10之间的随机整数呢?需要分为以下几步: 1 ...

  2. 2018.8.18 servlet使用的会话跟踪除session外还有哪些方式

    解释HTTP HTTP是一种无连接的协议,如果一个客户端只是单纯地请求一个文件(HTML或GIF),服务器端可以响应给客户端,并不需要知道一连串的请求是否来自于相同的客户端,而且也不需要担心客户端是否 ...

  3. EF 集合版 增删查改

  4. Python类型转换+序列操作+基本概念辨析速查手册

     第一部分是Python语言中基础中的基础,根据网上资料,合并如下:       1.类型转换     int(x [,base])  将x转换为一个整数     long(x [,base]) 将x ...

  5. JS isArray、typeof、instanceof

    Array.isArray() 用来检验是不是数组 var a = [1,2,3] console.log(typeof a); // object console.log(Array.isArray ...

  6. checkboxlist 如何配置数据源?

    <f:CheckBoxList runat="server" ColumnNumber="4" ColumnVertical="true&quo ...

  7. SpringBoot学习14:springboot异常处理方式4(使用SimpleMappingExceptionResolver处理异常)

    修改异常处理方法3中的全局异常处理Controller即可 package bjsxt.exception; import org.springframework.context.annotation ...

  8. 泉五培训Day4

    T1 收果子 题目 [题目描述] 有一个果园,有n棵果树依次排成一排,其中已知第 i 棵果树上结了ai个果子.现在要按照果树编号顺序依次收果子,对于一个能装v个果树的果篮,收果子从第1棵果树开始,如果 ...

  9. v-cloak

    v-cloak 不需要表达式 用法: 这个指令保持在元素上直到关联实例结束编译.和 CSS 规则如 [v-cloak] { display: none } 一起用时,这个指令可以隐藏未编译的 Must ...

  10. oracle时间计算

    1.在给定时间上加减天数 SQL> select to_char(to_date('20170531000000','yyyymmdd HH24:MI:SS')+4,'YYYYMMDDHH24M ...