Spring-AOP简介与底层实现机制——动态代理,java发展史百度百科

基于代理思想,对原来目标对象,创建代理对象,在不修改原对象代码情况下,通过代理对象,调用增强功能的代码,从而对原有业务方法进行增强

切面:需要代理一些方法和增强代码

AOP的应用场景

场景一:记录日志

场景二:监控方法运行时间 (监控性能)

场景三: 权限控制

场景四: 缓存优化 (第一次调用查询数据库,将查询结果放入内存对象, 第二次调用, 直接从内存对象返回,不需要查询数据库 )

场景五: 事务管理 (调用方法前开启事务, 调用方法后提交或者回滚、关闭事务 )

Spring AO

【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】

浏览器打开:qq.cn.hn/FTf 开源分享

P编程两种方式

方式一:Spring AOP使用纯Java实现,不需要专门的编译过程和类加载器,在运行期通过代理方式向目标类植入增强代码(编程复杂,不推荐)

方式二:Spring 2.0 之后支持第三方 AOP框架(AspectJ ),实现另一种 AOP编程 (推荐)

AOP编程相关术语

1.Aspect(切面): 是通知和切入点的结合,通知和切入点共同定义了关于切面的全部内容—它的功能、在何时和何地完成其功能

2.joinpoint(连接点):所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点.

3.Pointcut(切入点):所谓切入点是指我们要对哪些joinpoint进行拦截的定义.通知定义了切面的”什么”和”何时”,切入点就定义了”何地”.

4.Advice(通知、增强):所谓通知是指拦截到joinpoint之后所要做的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕通知(切面要完成的功能)

5.Target(目标对象):代理的目标对象

6.Weaving(织入):是指把切面应用到目标对象来创建新的代理对象的过程.切面在指定的连接点织入到目标对象

7.Introduction(引入)(不要求掌握):在不修改类代码的前提下, Introduction可以在运行期为类动态地添加一些方法或Field.

AOP编程底层实现机制

AOP 就是要对目标进行代理对象的创建, Spring AOP是基于动态代理的,分别基于两种动态代理机制: JDK动态代理和CGLIB动态代理

方式一:JDK动态代理

JDK动态代理,针对目标对象的接口进行代理 ,动态生成接口的实现类 (必须有接口)

过程要点

1.必须对接口生成代理

2.采用Proxy对象,通过newProxyInstance方法为目标创建代理对象。

该方法接收三个参数 :

(1)目标对象类加载器

(2)目标对象实现的接口

(3)代理后的处理程序InvocationHandler

3.实现InvocationHandler 接口中 invoke方法,在目标对象每个方法调用时,都会执行invoke

service层

//接口(表示代理的目标接口)
public interface ICustomerService {
//保存
void save();
//查询
int find();
}
//实现层
public class CustomerServiceImpl implements ICustomerService{

@Override
public void save() {
System.out.println(“客户保存了。。。。。”);
}

@Override
public int find() {
System.out.println(“客户查询数量了。。。。。”);
return 100;
}
}

JDK动态代理工厂

//专门用来生成jdk的动态代理对象的-通用
public class JdkProxyFactory{
//target目标对象
private Object target;

//注入target目标对象
public JdkProxyFactory(Object target) {
this.target = target;
}

public Object getProxyObject(){

/**

  • 参数1:目标对象的类加载器
  • 参数2:目标对象实现的接口
  • 参数3:回调方法对象
    */
    return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),
    new InvocationHandler(){
    public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
    //如果是保存的方法,执行记录日志操作
    if(method.getName().equals(“save”)){
    System.out.println(“增强代码:写日志了。。。”);
    }
    //目标对象原来的方法执行
    Object object = method.invoke(target, args);//调用目标对象的某个方法,并且返回目标对象
    return object;
    }
    });
    }
    }

测试方法

//目标:使用动态代理,对原来的方法进行功能增强,而无需更改原来的代码。
//JDK动态代理:基于接口的(对象的类型,必须实现接口!)
@Test
public void testJdkProxy(){
//target(目标对象)
ICustomerService target = new CustomerServiceImpl();
//实例化注入目标对象
JdkProxyFactory jdkProxyFactory = new JdkProxyFactory(target);
//获取 Object代理对象:基于目标对象类型的接口的类型的子类型的对象
//必需使用接口对象去强转
ICustomerService proxy = (ICustomerService)jdkProxyFactory.getProxyObject();
//调用目标对象的方法
proxy.save();
System.out.println("————————————————————");
proxy.find();
}

注意

JDK动态代理产生的对象不再是原对象

  • 错误:

CustomerServiceImpl proxy = (CustomerServiceImpl)jdkProxyFactory.getProxyObject();

  • 正确

ICustomerService proxy = (ICustomerService)jdkProxyFactory.getProxyObject();

方式二:Cglib动态代理

Cglib的引入为了解决类的直接代理问题(生成代理子类),不需要接口也可以代理

该代理方式需要相应的jar包,但不需要导入。因为Spring core包已经包含cglib ,而且同时包含了cglib 依赖的asm的包(动态字节码的操作类库)

//没有接口的类
public class ProductService {
public void save() {
System.out.println(“商品保存了。。。。。”);
}

public int find() {
System.out.println(“商品查询数量了。。。。。”);
return 99;
}
}

使用cglib代理

//cglib动态代理工厂:用来生成cglib代理对象
public class CglibProxyFactory implements MethodInterceptor{
private Object target;

//注入代理对象
public CglibProxyFactory(Object target) {
this.target = target;
}

//获取代理对象
//cglib动态代理工厂:用来生成cglib代理对象
public class CglibProxyFactory implements MethodInterceptor{
private Object target;

//注入代理对象
public CglibProxyFactory(Object target) {
this.target = target;
}

//获取代理对象

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值