代理模式 & spring aop具体应用
作者:互联网
无论是代理模式还是AOP核心思想都是在不修改原来业务代码前提下,进行原来代码的增强
一:代理模式
代理作用:可以在不修改原来代码的前提下,进行代码扩展。动态代理类在程序运行时通过发射机制动态生成
代理模式使用场合:客户端不直接访问实际对象,而通过代理对象作为桥梁来完成间接访问
1.静态代理VS动态代理
1.1静态代理:
静态代理:每一个不希望被修改的对象(SaveBusinessProcess)都要创建一个对应的代理类(SaveBusinessProcessProxy),这也正是静态代理的缺点。
比如,除了SaveBusinessProcess还有UpdateBusinessProcess,DeleteBusinessProcess等,使用静态代理都需要创建对应的代理UpdateBusinessProcessProxy,DeleteBusinessProcessProxy
初始SaveBusinessProcess在线上运行将数据存储到mysql——》在不更改SaveBusinessProcess存储数据到mysql前提下需要将这些数据保存到oracle——》新建代理类SaeBusinessProcessProxy,将SaveBusinessProcess作为成员变量
实例代码:
TestMain: public class BusinessProcessTest { public static void main(String[] args){ IBusinessProcess businessProcess=new SaveBusinessProcess(); IBusinessProcess businessProcessProxy=new SaveBusinessProcessProxy(businessProcess); businessProcessProxy.dataProcess(); } } Interface: public interface IBusinessProcess { public void dataProcess(); } Service: public class SaveBusinessProcess implements IBusinessProcess { @Override public void dataProcess() { //dataprocess(); --业务处理逻辑 System.out.println("save data process completed"); } } Proxy: public class SaveBusinessProcessProxy implements IBusinessProcess { private IBusinessProcess businessProcess; public SaveBusinessProcessProxy(IBusinessProcess businessProcess){ this.businessProcess=businessProcess; } @Override public void dataProcess() { //addProcess() --需要加强的代码 System.out.println("static proxy process"); this.businessProcess.dataProcess(); } }
控制台输出:
1.2 动态代理(JDK动态代理 && CGLIB动态代理)
mainTest: public class BusinessProcessTest { public static void main(String[] args){ ISaveBusinessProcess saveBusinessProcess=new SaveBusinessProcess(); IUpdateBusinessProcess updateBusinessProcess=new UpdateBusinessProcess(); IDeleteBusinessProcess deleteBusinessProcess=new DeleteBusinessProcess(); ISaveBusinessProcess saveBusinessProcessProxy= (ISaveBusinessProcess) new BusinessProcessProxy().bind(saveBusinessProcess); saveBusinessProcessProxy.save(); IUpdateBusinessProcess updateBusinessProcessProxy=(IUpdateBusinessProcess) new BusinessProcessProxy().bind(updateBusinessProcess); updateBusinessProcessProxy.update(); IDeleteBusinessProcess deleteBusinessProcessProxy=(IDeleteBusinessProcess) new BusinessProcessProxy().bind(deleteBusinessProcess); deleteBusinessProcessProxy.delete(); } } Interface: public interface ISaveBusinessProcess { public void save(); } public interface IUpdateBusinessProcess { public void update(); } public interface IDeleteBusinessProcess { public void delete(); } Service: public class SaveBusinessProcess implements ISaveBusinessProcess{ public void save(){ //save data into mysql process System.out.println("save data into mysql completed"); } } public class UpdateBusinessProcess implements IUpdateBusinessProcess{ public void update(){ //update data from mysql process System.out.println("update in mysql completed"); } } public class DeleteBusinessProcess implements IDeleteBusinessProcess{ public void delete(){ //delete data from mysql process System.out.println("delete data from mysql completed"); } } Proxy: public class BusinessProcessProxy implements InvocationHandler{ private Object obj ;//需要代理的目标对象 public Object bind(Object obj){ this.obj = obj; return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj .getClass().getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //需增强代码谢在invoke里 //save data into oracle process System.out.println("save data into oracle completed..."); //delete data from oracle process System.out.println("delete data from oracle completed..."); //update data into oracle process System.out.println("update data from oracle completed..."); return method.invoke(obj, args); } }
控制台输出:
save data into oracle completed...
delete data from oracle completed...
update data from oracle completed...
save data into mysql completed
save data into oracle completed...
delete data from oracle completed...
update data from oracle completed...
update in mysql completed
save data into oracle completed...
delete data from oracle completed...
update data from oracle completed...
delete data from mysql completed
二: AOP
AOP:它不需要专门的编译方式和特殊的类装载器,它在运行期通过动态代理方式来实现将目标类织入性能监视代码
1. aop核心概念
切面(Aspect):一个模块化的横切逻辑(也称横切关注点),可能会横切多个对象。
连接点(Join point):程序执行中的某个具体执行点。如上例中原对象(非代理对象)的方法。
增强处理:切面在某个特定连接点上执行的代码逻辑。
切入点(pointcut):对连接点的特征进行描述,可使用正则表达式,类似于Servlet的url-pattern,用于匹配连接点(方法)。增强处理与一个切入点表达式相关联,并在与这个切入点匹配的某个连接点运行。
目标对象:被一个或多个切面增强的对象。
AOP代理(Proxy):由AOP所创建的对象,实现执行增强处理方法等功能,可以使JDK动态代理也可以是CGLIB代理;如果是接口,则可以使用JDK动态代理,如果是类(比如service只有一个实现,不需要使用接口或者Controller层只有一个实现)则使用CGLIB代理
织入:将增强处理连接到应用程序中的类型或对象上的过程,叫织入。
增强处理类型:在原对象的方法连接点之前插入的增强处理叫前置增强,在其之后的叫后置增强。此外还要环绕增强、异常抛出增强、最终增强等类型。
通知(advice),5种通知方式
@Before
:前置通知,在调用目标方法之前执行通知定义的任务@After
:后置通知,在目标方法执行结束后,无论执行结果如何都执行通知定义的任务@After-returning
:后置通知,在目标方法执行结束后,如果执行成功,则执行通知定义的任务@After-throwing
:异常通知,如果目标方法执行过程中抛出异常,则执行通知定义的任务@Around
:环绕通知,在目标方法执行前和执行后,都需要执行通知定义的任务。
2.AOP常用注解
@Aspect:作用:把当前类声明为切面类。
@Before:
作用:把当前方法看成是前置通知。
属性:
value:用于指定切入点表达式,还可以指定切入点表达式的引用。
@AfterReturning
作用:把当前方法看成是后置通知。
属性:
value:用于指定切入点表达式,还可以指定切入点表达式的引用。
@AfterThrowing
作用:把当前方法看成是异常通知。
属性:
value:用于指定切入点表达式,还可以指定切入点表达式的引用。
@After
作用:把当前方法看成是始终通知。
属性:
value:用于指定切入点表达式,还可以指定切入点表达式的引用。
@Around
作用:把当前方法看成是环绕通知。
属性:
value:用于指定切入点表达式,还可以指定切入点表达式的引用。
@Pointcut
作用:指定切入点表达式
属性:
value:指定表达式的内容
@Order
作用: 指定切面执行顺序
@Aspect
// 切面执行顺序
@Order
(
3
)
实例:(将监控代码AspectDemo 织入业务代码AspectTestService中,实现业务代码和监控代码的解耦)
ProjectApplication: @SpringBootApplication public class ProjectApplication { public static void main(String[] args) { SpringApplication.run(ProjectApplication.class, args); } } Controller: @RestController @Slf4j public class AspectTestController { @Autowired private AspectTestService aspectTestService; @RequestMapping("aoptest") public void test(){ log.info("this is an aop controller..."); aspectTestService.test("abc"); // aspectTestService.testAgain(); } } Srvice: @Service @Slf4j public class AspectTestService { public void test(String name){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } log.info("this is an AOP test service ..."); } } AOP: @Aspect 定义切片类 @Component @Slf4j public class AspectDemo { @Before("pointCuteDemo()") public void doBefore(){ log.info("Aspect Demo before"); } @Around("pointCuteDemo()") public Object logPerformance(ProceedingJoinPoint pjp) throws Throwable { long starttime = System.currentTimeMillis(); String name = "-"; String result = "Y"; try { Object[] args=pjp.getArgs(); //获取方法参数值数组 MethodSignature methodSignature= (MethodSignature) pjp.getSignature(); //获取方法名 Class[] paramTypeArray=methodSignature.getParameterTypes(); //获取方法参数类型 name=methodSignature.toLongString(); log.info("args:{},methodSignature:{},paramTypeArray:{}",args,methodSignature,paramTypeArray); return pjp.proceed(); //pjp.proceed()上边内容在调用com.fql.example.project.aop.service包下任意方法之前执行;pjp.proceed()下边内容在调用com.fql.example.project.aop.service包下任意方法之后执行 } catch (Exception e) { result = "N"; throw e; } finally { long endtime = System.currentTimeMillis(); log.info("{},{},{}ms", name, result, endtime - starttime); } } @After("pointCuteDemo()") public void doAfter(){ log.info("Aspect Demo After"); } @Pointcut("execution(* com.fql.example.project.aop.service..*(..))") //service包下的任意类的任意方法时均会调用此方法 private void pointCuteDemo(){} }
参考:https://www.cnblogs.com/wangenxian/p/10885309.html
https://www.cnblogs.com/leifei/p/8263448.html
标签:spring,void,completed,代理,aop,oracle,data,public 来源: https://www.cnblogs.com/enhance/p/15814831.html