目录
一:引言
1.1企业级系统:
1.2那么如何去应对企业级应用开发
1.3 Spring的绿草丛
二:Spring的绿草丛
2.1 Spring 介绍
2.2 Spring两大核心技术
a.控制反转(IoC(Inversion of Control) / 依赖注入(DI))
b.面向切面编程(AoP)
2.3 Spring 优点
2.4 Spring工程构建
2.4.1Maven Spring依赖
2.4.2 Spring核心配置文件编写
2.4.3 完成控制反转及依赖注入的实例
2.4.4 Spring中的IoC产生的对象是否是单例模式 (是)
2.4.5延迟实例化
2.5 Bean的三种实例化方式
2.5.1构造方法方式【重点】
2.5.2静态工厂方式(了解)
2.5.3实例工厂方式(了解)
2.6 Bean的生命周期
2.7 Bean的销毁时机
三:应用XML编程实现AOP
3.1AOP的代理实现形式(一共有三种)
3.1.1 通过JDK动态代理实现
优点
术语概念
3.1.2通过CGLib动态代理实现
3.1.3 AOP术语
3.2 通过编程形式基于XML实现AOP
3.2 AOP使用场景
一:引言
1.1企业级系统:
- 大规模:用户数量多,数据规模大,功能众多
- 性能和安全要求高。
- 业务复杂
- 灵活多变(指的是用户的需求)
1.2那么如何去应对企业级应用开发

1.3 Spring的绿草丛
Spring : 轻量级框架(相比于EJB),JavaEE的春天,当前主流框架。
目标:使现有技术更加易用,实现代码最佳实践。
内容:IoC容器 ,AoP实现(俩大核心内容)
数据访问支持(简化JDBC/ORM框架 ,声明式事务)
web集成(核心框架SpringMVC)

二:Spring的绿草丛
2.1 Spring 介绍

2.2 Spring两大核心技术
a.控制反转(IoC(Inversion of Control) / 依赖注入(DI))
控制反转(Inversion of Control),将原来有我们来完成的实例化过程,交给容器来完成。将组件对象的控制权从代码本身转移到外部容器。
依赖注入。依赖于某一种媒介完成对某一个对象的初始化或者是赋值。
b.面向切面编程(AoP)
面向切面编程(Aspect Oriented Programming)
2.3 Spring 优点
- 低侵入式设计
- 独立于各种应用服务器
- 依赖注入特性将组件关系透明化,降低了耦合度
- 面向切面编程特性允许将通用任务进行集中式处理
- 与第三方框架的良好整合
2.4 Spring工程构建
2.4.1Maven Spring依赖
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.22</version>
</dependency>
2.4.2 Spring核心配置文件编写
<?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"></beans>
2.4.3 完成控制反转及依赖注入的实例
<!-- 控制反转 -->< bean id = "userInfo" class = "com.domain.UserInfo" ></ bean >
<!-- 完成依赖注入 DI -->< property name = "username" value = " 张三 " />< property name = "content" value = " 刘家豪大笨蛋! " />
<bean id="userInfo" class="com.domain.UserInfo"><!--完成依赖注入 DI--><property name="username" value="张三 " /><property name="content" value="刘家豪大笨蛋! " /></bean>
bean的id名称,在同一个配置文件下,是只能拥有一个,不能够出现重复的id名称!如果出现相同的id,则会报如下错误:
测试:
@Testpublic void testInit () {// 步骤 1 :获取到 ApplicationContext 对象//ClassPathXmlApplicationContext: 代表从类路径下加载 xml 配置文件,返回ApplicationContext 的对象ApplicationContext ctx = new ClassPathXmlApplicationContext ( "applicationContext.xml" ) ;// 步骤 2 :从 ApplicationContext 容器中获取到 userInfo 的对象UserInfo userInfo = ( UserInfo ) ctx . getBean ( "userInfo" ) ;userInfo . say ();}
2.4.4 Spring中的IoC产生的对象是否是单例模式 (是)
scope 属性代表设置当前当前 bean 的作用域。singleton:单例prototype:每次调用时都会创建一个新的对象。<bean name = "helloSpring" class = "com.csi.bean.HelloSpring" scope = "singleton" ><!--DI--><property name = "hello" value = " 今天天气好晴朗 " /></bean>
//ClassPathXmlApplicationContext: 代表从类路径下加载 xml 配置文件,返回 ApplicationContext的对象ApplicationContext ctx = new ClassPathXmlApplicationContext ( "applicationContext.xml" ) ;// 步骤 2 :从 ApplicationContext 容器中获取到 userInfo 的对象UserInfo userInfo = ( UserInfo ) ctx . getBean ( "userInfo1" ) ;userInfo . say ();System.out.println(userInfo);userInfo = ( UserInfo ) ctx . getBean ( "userInfo1" ) ;userInfo . say ();System.out.println(userInfo);以上代码,对同一个 bean 进行两次调用,得到对象是同一个对象,说明在 Spring 的设计当中,所使用的是单例设计模式!每一个调用的 bean ,都会生成一个新的对象。
2.4.5延迟实例化
< bean id = "userInfo1" class = "com.domain.UserInfo" ><!-- 完成依赖注入 DI -->< property name = "username" value = " 张三 " />< property name = "content" value = " 刘家豪大笨蛋! " /></ bean >< bean id = "userInfo2" class = "com.domain.UserInfo" ><!-- 完成依赖注入 DI -->< property name = "username" value = " 李四 " />< property name = "content" value = " 翟雪松大帅哥! " /></ bean >
虽然都是对同一个类进行实例化,但是每一个bean就代表着一个对象。
当Spring加载配置文件时,默认情况下,就会将所有配置的bean全部实例化。如果在Spring的bean节点中,配置了lazy-init的属性,就会实现延迟初始化的效果,即在spring容器启动时,并不会立刻初始化该对象,直到获取该对象的id或者是name时,才会初始化对象。<bean name = "helloSpring" class = "com.csi.bean.HelloSpring" scope = "singleton"lazy-init = "true" ><!--DI--><property name = "hello" value = " 今天天气好晴朗 " /></bean>
// 需要先加载 Spring 核心配置文件 , 如果设置了 lazy-init ,调用该语句时不会初始化对象ApplicationContext ctx = new ClassPathXmlApplicationContext ( "applicationContext.xml" ) ;// 调用时才会初始化对象HelloSpring helloSpring = ( HelloSpring ) ctx . getBean ( "helloSpring" );
2.5 Bean的三种实例化方式
2.5.1构造方法方式【重点】
- BookDaoImpl实现类
public class BookDaoImpl implements BookDao {public BookDaoImpl () {System . out . println ( "book dao constructor is running ...." );}public void save () {System . out . println ( "book dao save ..." );}}
- applicationContext.xml配置
<!-- 方式一:构造方法实例化 bean--><bean id = "bookDao" class = "com.csi.dao.impl.BookDaoImpl" />
- AppForInstanceBook测试类
public class AppForInstanceBook {public static void main ( String [] args ) {ApplicationContext ctx = newClassPathXmlApplicationContext ( "applicationContext.xml" );BookDao bookDao = ( BookDao ) ctx . getBean ( "bookDao" );bookDao . save ();}}
2.5.2静态工厂方式(了解)
- orderDao接口和orderDaoImpl实现类
public interface OrderDao {public void save ();}public class OrderDaoImpl implements OrderDao {public void save () {System . out . println ( "order dao save ..." );}}
- OrderDaoFatory工厂类
// 静态工厂创建对象public class OrderDaoFactory {public static OrderDao getOrderDao (){System . out . println ( "factory setup...." );return new OrderDaoImpl ();}}
- applicationContext.xml配置
<!-- 方式二:使用静态工厂实例化 bean--><bean id = "orderDao" class = "com.csi.factory.OrderDaoFactory" factorymethod = "getOrderDao" />
- AppForInstanceOrder测试类
public class AppForInstanceOrder {public static void main ( String [] args ) {ApplicationContext ctx = new ClassPathXmlApplicationContext ( "applicationContext.xml" );OrderDao orderDao = ( OrderDao ) ctx . getBean ( "orderDao" );orderDao . save ();}}
2.5.3实例工厂方式(了解)
- UserDao接口和UserImpl实现类

- UserDaoFactory工厂类

- applicationContext.xml配置

- AppForInstanceUser测试类

2.6 Bean的生命周期
- 使用init-method及destroy-method


测试类(使用实现类类型,接口类型没有close方法)

- 实现InitializingBean, DisposableBean接口

心得:如果既实现了这俩个接口,又手写了初始化和销毁方法。经过测试得知,实现接口的初始化和注销方法优先执行。
2.7 Bean的销毁时机
- 容器关闭前触发bean的销毁
- 关闭容器方式:
三:应用XML编程实现AOP
3.1AOP的代理实现形式(一共有三种)
3.1.1 通过JDK动态代理实现
优点
- 不用创建类文件
- 当修改了接口中的方法时,不会影响代理类
- 不用给不同的目标随时创建代理
术语概念
- 1目标类:实现了功能接口的实现类对象
- 代理类:作为调用类和目标类之间的桥接
- 调用类:需要调用目标类方法来完成值的获取
- OCP原则:程序设计的一个考虑,类设计的时候尽量避免方法当中代码的二次修改,但是欢迎类设计者扩展一个类的功能(方法)
- 耦合度:一个类过于依赖于另一个类,就会产生耦合性
注意:JDK的动态代理,是要求必须拥有接口的。Spring能够对任何的一个对象都进行代理设计,此时如果某个对象没有对应的接口,只是单单的利用JDK动态代理,则无法创建对应的代理对象。Spring AOP就会采用CGLib生成。
例子:


3.1.2通过CGLib动态代理实现
3.1.3 AOP术语

- 连接点(JoinPoint):正在执行的方法,例如:update()、delete()、select()等都是连接点。 每个方法不仅仅只有一个连接点,方法前中后都可能成为一个连接点。
- 切入点(Pointcut):进行功能增强了的方法,例如:update()、delete()方法,select()方法没有被增强所以不是切入点,但是是连接点。

- 通知(Advice):在切入点前后执行的操作,也就是增强的共性功能
在SpringAOP中,功能最终以方法的形式呈现
- 通知类:通知方法所在的类叫做通知类
- 切面(Aspect):描述通知与切入点的对应关系,也就是哪些通知方法对应哪些切入点方法。
3.2 通过编程形式基于XML实现AOP
- 引入aspectjwarver环境
<dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.9.1</version></dependency>
- 修改核心配置文件

- 编写增强通知类
package com.csi.proxy;import org.aopalliance.intercept.Joinpoint;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;import java.util.Arrays;public class LogManagerAdvice {//构造public LogManagerAdvice(){System.out.println("建立数据库连接.....");}//前置增强public void before(JoinPoint joinpoint){System.out.println("被增强的类:"+joinpoint.getTarget().getClass().getName()+ "被拦截的方法:" +joinpoint.getSignature().getName()+"参数是:"+ Arrays.toString(joinpoint.getArgs()));System.out.println("开始记录日志。。。。");}//后置增强public void afterReturning(JoinPoint joinPoint ,Object o){System.out.println("结束日志记录。。。");}//异常通知public void afterThrowing(JoinPoint joinPoint,RuntimeException e){System.out.println(joinPoint.getTarget()+"的"+joinPoint.getSignature().getName()+",报出的信息是:"+e);}//最终通知public void after(JoinPoint joinPoint){System.out.println("最终通知:"+joinPoint.getTarget()+"的"+joinPoint.getSignature().getName()+",参数是"+Arrays.toString(joinPoint.getArgs()));}//环绕通知public void afterAround(ProceedingJoinPoint pjp){System.out.println("开启事务.....");try {Object result = pjp.proceed();System.out.println("事务提交....");} catch (Throwable e) {e.printStackTrace();System.out.println("事务回滚....");}finally {System.out.println("释放SqlSession对象");}}
}
- 在核心配置文件中添加aop配置

- 测试
ApplicationContext ctx = new ClasspathXMLApplicationContext ( "applicationXXX.xml" ) ;Object obj = ctx . getBean ( "id" ) ;obj . xxx () ;
- 结论
从实验的结果中,发现 AOP 灵活度非常高,当需要或不需要前置或后置通知时,只需要进行配置即可。
3.2 AOP使用场景
- 日志
- 权限
- 事务管理














