Spring框架Aop实现—代理模式介绍(4)

Spring框架Aop实现—代理模式介绍

针对上面介绍的ioc思想,这里开始介绍aop的核心思想即面向切面编程思想。本内容讲的是基本的代理模式的介绍,后续的动态代理会慢慢更新。谢谢大家的阅读学习。

1、AOP概念

AOP是面向切面编程的意思,是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。

AOP的作用:不修改源码的情况下,程序运行期间对方法进行功能增强。

好处:

  • 减少代码的重用,提高开发效率便于维护。
  • 专注于核心业务开发。

针对上述几点,首先需要理解的是一般的工程项目比如编写一个存储数据的模块,可能往往会需要编写事务、日志等其他模块,此时就可以把这些地方分发出去,到最后测试的时候再拿回来。

2、AOP的实现机制-动态代理

2.1 代理模式的概念

代理:顾名思义就是别人帮你制作。

代理模式:在一个原有功能的基础上添加新的功能。

分类:代理模式分为静态代理动态代理

2.2 传统的核心与服务编写方式:编写在一起

package com.jpg.service;
public class TeamService {
public void add(){
try {
System.out.println("开始事务");
System.out.println("TeamService---- add----");// 核心业务
System.out.println("提交事务");
} catch (Exception e) {
e.printStackTrace();
System.out.println("回滚事务");
}
}
}

首先在上面写的是一般初学者的编写方法,但是缺点很明显!!比如如果一个服务有很多次结果的显示——按200、201、202等等进行分别展示自己的事务,那不就要编写很多的类吗?

所以,后面的静态代理解决了传统的高耦合的问题,增加了一点扩展性。

2.3 静态代理

静态代理的实现方法有很多种,比如基于类的静态代理和基于接口的静态代理等等。

2.3.1 基于类的静态代理

基于类的静态代理相对于传统的编写方法在于创建核心业务的子类继承核心业务类,在主方法调用核心方法类。这听上去其实跟传统的方法没有很大的区别,而相较于前有了直接的将核心业务与服务方法分开管理的思想。

package com.jpg.service;
public class TeamService {
public void add(){
System.out.println("TeamService---- add----");// 核心业务
}
}
package com.jpg.staticproxy;
import com.jpg.service.TeamService;
/**
* 基于类的静态代理:
* 要求继承被代理的类
* 弊端:每次只能代理一个类
*/
public class ProxyTeamService extends TeamService {
public void add(){
try {
    System.out.println("开始事务");
    super.add();//核心业务就是由被代理对象完成 ;其他服务功能由代理类完成
    System.out.println("提交事务");
    }catch (Exception e){
    System.out.println("回滚事务");
}
}
}
public static void main(String[] args) {
TeamService ser=new ProxyTeamService();
ser.add();
}

其中,弊端也很明显。因为代理类只能代理一个类呀。这还是没有跳出传统的核心问题。

2.3.2 基于接口的静态代理

静态代理为核心业务**保存add,**创建一个接口,通过接口暴露被代理的方法。

第一步:创建定义一个接口以实现核心方法。

package com.jpg.service;
public interface IService {
    void add();
}

第二步:创建核心业务类(被代理类)实现第一步的接口

package com.jpg.service;
public class TeamService implements IService{
@Override
public void add(){
    System.out.println("TeamService---- add----");// 核心业务
}
}
package com.jpg.service;
public class UserService implements IService{
@Override
public void add() {
    System.out.println("UserService---- add-----");
}
}

第三步:创建编写基于接口的服务类(代理类)。此时代理类和被代理类实现一个接口。

这里我们编写事务类服务和日志类服务。

事务类:

package com.jpg.staticproxy;
import com.jpg.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.jpg.staticproxy;
import com.jpg.service.IService;
public class ProxyLogService implements IService {
private IService service;//被代理对象
public ProxyLogService(IService service) {
this.service = service;
}
@Override
public void add() {
try {
System.out.println("开始日志");
service.add();//核心业务就是由被代理对象完成 ;其他服务功能由代理类完成
System.out.println("结束日志");
}catch (Exception e){
System.out.println("异常日志");
}
}
}

第四步:测试一下最后的核心代码与服务方法的结合。

public static void main(String[] args) {
TeamService teamService=new TeamService();//被代理对象
UserService userService=new UserService();//被代理对象
ProxyTranService tranService=new ProxyTranService(userService);//事务代理对象--一级代理
//tranService.add();//代理对象干活
ProxyLogService logService=new ProxyLogService(tranService);//日志的代理对象--二级代理
logService.add();
}

这里比较巧妙的是,创建一级对象和二级对象时如果对先后顺序有要求即通过如上示例调用。一级调用被代理者作为参数;二级调用以第一级别的代理的结果为基础,以一级代理作为其参数进行调用。

注意的是,如果日后对软件的更新需要修改接口方法,其他许多类都会受到或多或少的影响。

2.3.3 提取切面代码作为AOP接口

什么意思呢?就是将核心业务的各个环节插入某些事务处理环节等等。比如说运行核心业务前要编写事务和日志;到了编译核心代码结束后需要关闭事务和日志;报错了事务和日志需要填写相应的报错信息等等方面。

这就是动态代理面向切面编程的前置思想。

第一步:定义并设置切面接口下的方法。

package com.jpg.aop;
/**
* 切面:服务代码,切入到核心代码中,切入到哪里,给了四个位置
*/
public interface AOP {
void before();
void after();
void exception();
void myFinally();
}

这里的方法如中译理解一样,分别在核心业务前、后、异常处理和最后设置服务方法插入。

第二步:设置服务类(代理类)实现接口

事务类:

package com.jpg.aop;
public class TranAOP implements AOP {
@Override
public void before() {
System.out.println("事务----before");
}
@Override
public void after() {
System.out.println("事务----after");
}
@Override
public void exception() {
System.out.println("事务----exception");
}
@Override
public void myFinally() {
System.out.println("事务----myFinally");
}
}

日志类:

package com.jpg.aop;
public class LogAop implements AOP{
@Override
public void before() {
System.out.println("日志----before");
}
@Override
public void after() {
System.out.println("日志----after");
}
@Override
public void exception() {
System.out.println("日志----exception");
}
@Override
public void myFinally() {
System.out.println("日志----myFinally");
}
}

第三步:设置服务层,将核心业务和服务被代理合并起来

package com.jpg.staticproxy;
import com.jpg.aop.AOP;
import com.jpg.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 teamService=new TeamService();//被代理对象--核心内容
AOP logAop=new LogAop();//切面-服务内容
AOP tranAop=new TranAOP();
IService service=new ProxyAOPService(teamService,logAop); //代理对象--一级
代理
IService service2=new ProxyAOPService(service,tranAop);//代理对象--二级代理
service2.add();
}

2.4 总结静态代理

总结静态代理:
可以做到不修改目标对象的功能前提下对目标对象进行扩展。
缺点:
1)代理对象需要与目标对象实现的接口一致,所以会有很多代理类。
2)一旦接口添加方法,目标对象和代理对象都要进行维护

谢谢大家的阅读,还请大家批评指正!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Xiao艾扶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值