0 复习
- FactoryBean技术(用于创建复杂对象)
复杂对象:底层不能直接通过new构造方法创建,通常需要若干步骤才能创建的对象。比如:Connection、SqlSession
- 编码 implements FactoryBean
- 配置 通过bean标签配置
- 配置文件
- import标签
- xsd使用规则
- 拆分jdbc.properties文件
- 概念总结 IOC和DI
- Spring整合Struts2
导入依赖:spring-web struts2-spring-plugin
- web.xml 在tomcat启动应用时,创建Spring工厂 <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
- Struts2从Spring工厂中获取Action applicationContext.xml bean标签配置action和service 注意: action需要多例 struts.xml <action name="路径" class="bean的id"></action>
- 注解开发 Component(Controller、Service、Repository)替换bean标签 Autowired替换property标签
Spring AOP
1 代理设计模式
1.1 解决的问题
image-20200602101013042
要不要在业务层中定义额外功能?
业务调用者的角度:需要,业务方法中需要使用这些额外功能 软件设计者的角度:不需要,定义后会造成代码的频繁修改
矛盾的解决方案:代理模式
1.2 代理模式
image-20200602102246281
矛盾:
房东不愿意提供额外功能(带看房,车接车送),因为麻烦 租客必须要使用这些额外功能
矛盾的解决方案:中介
中介代理了房东的出租房屋的方法,同时提供额外的功能。 房东无需亲自和租客打交道,节省时间。租客也可以享受完整的服务。
在程序中,Action(租客) 和 Serivce(房东) 的矛盾,也可以通过添加一个代理类解决。
1.3 静态代理
image-20200602103550535
实战:
接口:
代码语言:javascript复制public interface UserService {
public boolean login(String username,String password);
public void removeUser(Integer id);
}
原始实现类:
代码语言:javascript复制public class UserServiceImpl implements UserService {
@Override
public boolean login(String username, String password) {
System.out.println("username = [" username "], password = [" password "]");
return false;
}
@Override
public void removeUser(Integer id) {
System.out.println("id = [" id "]");
}
}
代理实现类:
代码语言:javascript复制public class UserServiceProxy implements UserService {
private UserService userService = new UserServiceImpl();
@Override
public boolean login(String username, String password) {
System.out.println("开启事务");
boolean result = userService.login(username,password);
System.out.println("结束事务");
return result;
}
@Override
public void removeUser(Integer id) {
System.out.println("开启事务");
userService.removeUser(id);
System.out.println("结束事务");
}
}
使用者:
代码语言:javascript复制public class UserAction {
private UserService userService = new UserServiceProxy();
public String login(){
userService.login("xiaohei", "123456");
return "success";
}
public String removeUser(){
userService.removeUser(1);
return "success";
}
}
2 Spring动态代理
静态代理的问题:
- 随着额外功能的增多,代理类数量随之增多,不利于管理
- 代理类冗余,存在多个代理类提供相同的功能
解决方案:动态代理
Spring动态代理:无需程序员手动编写代理类,只需要提供额外功能代码,然后由Spring框架自动的为原始类生成有增强功能的代理类。
好处:提高开发效率。
开发步骤:
额外引入以下2个依赖:spring-aop aspectjweaver
代码语言:javascript复制<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.26.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>
- 创建原始类型对象 <bean id="标识" class="原始(目标)类全类名"></bean>
- 定义额外功能。实现Spring的特定接口 public class MyMethodBeforeAdvice implements MethodBeforeAdvice { @Override /* method: 原始类型中方法 args: 参数 target: 原始对象 */ public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println("before..."); } }
- 配置额外功能类 <!-- 配置功能增强类 --> <bean id="myBeforeAdvice" class="com.bcl.advice.MyMethodBeforeAdvice"/>
- 定义切入点:决定额外功能添加到哪个位置
- 组装 <aop:config> <!-- 定义切入点--> <aop:pointcut id="myPointCut" expression="execution(* com.bcl.service.*.*(..))"/> <!-- 组装 --> <aop:advisor advice-ref="myBeforeAdvice" pointcut-ref="myPointCut"/> </aop:config>
名词(术语)解释:
- 原始类(目标类):提供核心功能的类
- 原始方法(目标方法):原始类中没有加入额外功能的方法
- 额外功能(增强):用于增强原始方法的代码
3 Spring动态代理的实现流程
image-20200602114248141
4 增强(Advice)
4.1 前置增强
增强会在目标方法前执行,实现接口 MethodBeforeAdvice
public class MyMethodBeforeAdvice implements MethodBeforeAdvice {
@Override
/*
method: 原始方法
args: 调用方法时的实参列表
target: 原始对象
*/
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("method = [" method "], args = [" Arrays.toString(args) "], target = [" target "]");
System.out.println("target.getClass() = " target.getClass());
System.out.println("前置增强");
}
}
4.2 后置增强
增强代码会在目标方法正常return后执行,实现接口 AfterReturningAdvice
public class MyAfterReturningAdvice implements AfterReturningAdvice {
/*
returnValue: 原始方法正常结束后的返回值
method: 原始方法
args: 实参列表
target: 原始对象
*/
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("后置增强");
}
}
4.3 异常增强
增强代码在目标方法发生异常时执行,实现接口 ThrowsAdvice
public class MyThrowsAdvice implements ThrowsAdvice {
/*
method: 原始方法
args: 实参列表
target: 原始对象
throwable: 原始方法运行时的异常
*/
public void afterThrowing(Method method, Object[] args,Object target, Throwable throwable){
System.out.println("异常增强");
}
}
4.4 环绕增强
增强代码在目标方法前后以及异常时都可以执行,实现接口 MethodInterceptor
image-20200602144422389
代码语言:javascript复制public class MyRoundAdvice implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation pj) throws Throwable {
System.out.println("前置增强");
Object result = null;
try {
//放行:调用原始方法
result = pj.proceed();
System.out.println("后置增强");
}catch(Exception e){
System.out.println("异常增强");
throw e;
}finally{
System.out.println("最终增强");
}
return result;
}
}
5 切入点详解
切入点:需要做功能增强处理的位置,可以通过切入点表达式描述。
5.1 execution表达式[重点]
image-20200602150619051
实战中,使用 execution(* com.bcl.service.*.*(..))
添加额外功能。
5.2 args表达式
用来匹配特定参数的方法。
args(参数列表)
5.3 within表达式
用来匹配特定的类,根据类名匹配。
within(类名表达式)
5.4 @annotation表达式
@annotation(注解类型),通过特定的注解来匹配类。
- 自定义一个注解 public @interface MyAnnotation { }
- 使用自定义注解描述方法(实现类中的方法) public class UserServiceImpl implements UserService { @Override @MyAnnotation public boolean login(String username, String password) { System.out.println("username = [" username "], password = [" password "]"); return false; } @Override public void removeUser(Integer id) { System.out.println("id = [" id "]"); //int i = 10/0; } }
- 切入点配置为 @annotation(自定义注解类型) <aop:pointcut id="myPointCut" expression="@annotation(com.bcl.annotation.MyAnnotation)"/>
5.5 表达式的运算符
表达式之间可用过 and or not运算。
6 Spring AOP
AOP(Aspect Oriented Programming)面向切面编程。
OOP(Object Oriented Programming)面向对象编程。
6.1 OOP(面向对象编程)
面向对象编程以对象为单位进行编程,抽取共性方法,通过继承重用这些方法。
image-20200602153645027
6.2 Spring AOP
AOP为了解决程序中零散的共性代码的复用问题,是OOP有力补充。
- 增强:共性代码,额外功能。比如:事务、性能分析
- 切入点:添加额外功能的方法的位置
- 织入(编织):将增强添加到切入点的过程
- 切面:在切点织入增强代码后形成的一个几何平面的概念
image-20200602154757972
面向切面编程的要素:增强、切点和织入
面向切面编程的作用:灵活的以非侵入的方式(非耦合式)为现有的方法增强功能。
Spring切面编程的步骤:
- 配置原始类型对象
- 定义额外功能(增强)
- 配置增强类
- 定义切入点
- 编织
7 数据库中事务的隔离级别
事务的隔离级别:事务并发执行时,微观上多个执行时间相近的事务相互影响的问题。
标准的隔离级别4种:
隔离级别 | 特点 | 问题 |
---|---|---|
READ_UNCOMMITTED | 可以读取到未提交的事务 | 脏读 |
READ_COMMITTED | 只能读到已经提交的事务 | 不可重复读 |
REPEATABLE_READ | 同1个事务中读取到数据始终一致 | 幻影读 |
SERIALIZABLE | 序列化读,不允许并发操作 | 性能差 |
Oracle数据库,只支持2种:READ——COMMITTED
和 SERIALIZABLE
,MySQL支持4种。
MySQL隔离级别的演示:
- 确认MySQL的存储引擎 show engines;
- 查看隔离级别 select @@session.tx_isolation;
- 设置隔离级别 set @@session.tx_isolation=0 | 1 | 2 | 3
- 开启事务 begin;
- 结束事务 commit; rollback;
「❤️ 帅气的你又来看了我」
如果你觉得这篇内容对你挺有有帮助的话:
- 点赞支持下吧,让更多的人也能看到这篇内容(收藏不点赞,都是耍流氓 -_-)
- 欢迎在留言区与我分享你的想法,也欢迎你在留言区记录你的思考过程。
- 觉得不错的话,也可以关注 编程鹿 的个人公众号看更多文章和讲解视频(感谢大家的鼓励与支持