Spring 核心之 AOP
什么是 AOP
AOP 为 Aspect Oriented Programming 的缩写,意思为面向切面编程,是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。
AOP的作用:不修改源码的情况下,程序运行期间对方法进行功能增强
好处:
1、减少代码的重复,提高开发效率,便于维护。
2、专注核心业务的开发
核心业务和服务性代码混合在一起
开发中:各自做自己擅长的事情,运行的时候将服务性代码织入到核心业务中。
通过Spring工厂自动实现将服务性代码以切面的方式加入到核心业务代码中。
AOP 的实现机制-动态代理
什么是代理模式
代理:自己不用做,交给别人做
代理模式:在一个原有功能的基础上添加新的功能
分类:静态代理和动态代理
静态代理
原有方式:核心业务和服务方法都编写在一起
package com.imok.service;
public class StudentService{
public void add(){
try{
System.out.println("开始事务");
System.out.println("TeamService---- add----");//核心业务
System.out.println("提交事务");
} catch (Exception){
e.printStackTrace();
System.out.println("回滚事务");
}
}
}
基于类的静态代理
将服务性代码分离出来,核心业务-保存业务中只有保存功能
package com.imok.service;
public class StudentService{
public void add(){
System.out.println("StudentService---- add----");//核心业务
}
}
package com.imok.staticproxy;
import com.imok.service.StudentService;
/**
* 基于类的静态代理:
* 要求继承被代理的类
* 弊端:每次只能代理一个类
*/
public class ProxyStudentService extends StudentService{
public void add(){
try{
System.out.println("开始事务");
super.add();//核心业务就是被代理对象完成:其他服务功能由代理类完成
System.out.println("提交事务");
}catch(Exception e){
System.out.println("回滚事务");
}
}
}
public static void main(String[] args){
StudentService ser = new ProxyStudentService();
ser.add();
}
ps:静态代理有一个弊端,代理类只能代理一个类
基于接口的静态代理
为核心业务(保存add)创建一个接口,通过接口暴露被代理的方法
要求:代理类和被代理类都实现了同一个接口
package com.imok.service;
/**
* 接口定义核心方法
*/
public interface IService {
void add();
}
package com.imok.service;
public class StudentService implements IService{
@Override
public void add(){
System.out.println("StudentService---- add----");//核心业务
}
}
package com.imok.service;
public class UserService implements IService{
@Override
public void add(){
System.out.println("UserService---- add----");
}
}
package com.imok.staticproxy;
import com.imok.service.IService;
/**
* 基于接口静态代理
* 代理类和被代理类实现同一个接口
*/
public class ProxyTranService implements IService {
private IService service;//被代理的对象
public ProxyTranService(IService service){
this.service = service;
}
@Override
public void add(){
try{
System.out.println("开始事务");
service.add();//核心业务就是由被代理对象完成,其他服务功能由代理对象完成
System.out.println("提交事务");
}catch (Exception e){
System.out.println("回滚事务");
}
}
}
package com.imok.staticproxy;
import com.imok.service.IService;
public class ProxyLogService implements IService {
private IService service;//被代理对象
public ProxyLogService(IService service){
this.service = service;
}
@Override
public void add(){
try{
System.out.pritnln("开始日志");
service.add();//核心业务
System.out.println("结束日志");
}catch(Exception e){
System.out.prinln("异常日志")
}
}
}
测试类:
public static void main(String[] args){
StudentService studentService = new StudentService();//被代理对象 学生类
UserService userService = new UserService();//被代理对象 用户类 (记得随便创建一个实体类)
ProxyTranService tranService=new ProxyTranService(userService);//事务代理 对象--一级代理
//tranService.add();//代理对象工作
ProxyLogService logService=new ProxyLogService(tranService);//日志的代理对 象--二级代理logService.add();
}
提取出切面代码,作为AOP接口
共有4个位置可以将切面代码编织进入核心业务代码中。
package com.imok.aop;
/**
* 切面,服务代码,切入到核心代码中
*/
public interface AOP{
void before();
void after();
void exception();
void myFinally();
}
package com.imok.aop;
public class TranAop implements AOP{
@Override
public void before(){
System.out.pritnln("事务---before");
}
@Override
public void exception(){
System.out.pritnln("事务---exception");
}
@Override
public void myFinally(){
System.out.pritnln("事务---myFinally");
}
@Override
public void after(){
System.out.pritnln("事务---after");
}
}
package com.imok.aop;
public class LogAop implements AOP{
@Override
public void before(){
System.out.pritnln("日志---before");
}
@Override
public void exception(){
System.out.pritnln("日志---exception");
}
@Override
public void myFinally(){
System.out.pritnln("日志---myFinally");
}
@Override
public void after(){
System.out.pritnln("日志---after");
}
}
修改下 ProxyAOPService 类
package com.imok.staticproxy;
import com.imok.aop.AOP;
import com.imok.service.IService;
public class ProxyAOPService implements IService{
private IService service;//被代理对象
private AOP aop;//要加入切面
public ProxyAOPService(IService service,AOP aop){
this.service = service;
this.aop = aop;
}
@Override
public void add(){
try{
aop.before();
service.add();
aop.after();
}catch (Exception e){
aop.exception();
}finally{
aop.myFinally();
}
}
}
@Test
public void test02(){
IService studentService = new StudentService();//被代理对象--核心内容
AOP logAop = new LogAop();//切面-服务内容
AOP tranAop = new TranAop();
IService service = new ProxyAOPService(studentService,logAop);//代理对象--一级代理
IService service = new ProxyAOPService(studentService,TranAop);//代理对象--二级代理
service.add();
}
总结静态代理:
1 可以做到在不修改目标对象的功能前提下,对目标对象功能扩展
2 缺点:
因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类,类一多,一旦接口增加方法,目标对象与代理对象都要维护