aop实现原理-动态代理&CGLib代理

那接下来的话,那咱们Spring当中,这个AOP,咱们先说概念,咱们先不写具体代码,咱们就是聊,

聊Spring的AOP,Spring能帮我们干啥呢,我告诉你,Spring他作为对象的容器,Spring作为对象的容器,

说白了,他是能够帮我们,进行对容器中的对象,进行生成代理对象的一个功能,Spring能够对容器中管理的

对象,能够生成动态代理对象的,能理解啥意思不,你们以前学过动态代理技术,以前咱们写动态代理对象,

咱们得自己写代码,刚才我给你写的代码Proxy.newProxyInstance,然后里面传xx参数,以前是咱们自己要调这个

方法,以前我们要使用动态代理,我们需要自己调用,下面这个方法,然后呢来生成代理对象,而有了Spring之后,

Spring非常体贴,Spring能帮我们生成代理对象,生成这个代理对象,不需要调用这个方法了,只需要拿配置文件配

就可以,或者拿注解配就可以,他就自动产生代理对象,知道啥意思不,那他为什么叫AOP,他生成代理对象为什么叫

AOP,那道理很简单,那就是因为我左边这个图,你想,那这样Spring能够帮我们生成动态代理,那能不能让Spring帮我

Service实现动态代理,然后我告诉Spring,你在生成动态代理的时候,你这个动态代理,给我每一个Service,添加管理事务

的代码,Spring一听,弄个代理对象,弄出来之后,这样的话,咱们只需要写一遍事务代码,相当于给所有的Service都加上了,

这样的话,AOP思想都体现出来了,所以,AOP这种东西思想,是咱们使用之后,其实你要说SpringAOP的本质,他就是帮我们

生成动态代理,能明白啥意思不,所以为什么要使用AOP呢,这个问题太抽象了,明白啥意思不,所以这个Spring,其实SpringAOP

就是啥啊,它能够帮我们生成动态代理对象而已,重点就是这一点,咱们学SpringAOP,学的就是这玩意,让Spring指挥我们代理对象,

而不是,像以前一样,自己手写动态代理对象,这就是学习SpringAOP,学习的要点,而你学习会了能让Spring帮我们代理对象了,

是不是你就能够完成AOP思想来开发了,是不是这么一个关系,所以这就是学习SpringAOP

这就是学习SpringAOP,他这个词叫的太大了,具体就是Spring能够动态帮我们创建代理对象,

下面就是Spring实现AOP的原理,实现AOP的原理,其实提到了一个,实际上是什么技术呢,动态代理

技术,然后呢除了这个以外,还有一个技术,叫做cglib代理技术,这两种代理技术,分别介绍一下,

为什么要选择两种代理技术,来帮我们产生代理对象,动态代理你们学过,你们知道,动态代理他在

使用的时候有一个局限性,就是必须要有接口,说一下,被代理对象,必须要实现接口,才能产生代理对象,

因为刚才这个方法写出来也看到了,咱们传的话,第二个参数,是不是接口的数据,这个是不是要你传被

代理对象,要实现的接口,在动态代理的地方当中,如果没有接口,将不能使用动态代理,那这样的话你想,

如果Spring在给我们生成产生代理的时候,他只封装了动态代理的技术,那如果我们想要生成代理的对象,

没有接口,是不是做不到啊,于是为了能够保证每一个对象,都能够实现动态代理对象,所以又融入了一个

第三方代理的技术,cglib代理,这个代理技术,它是可以对任何类生成代理,因为它代理的原理是什么,因为

他对目标对象进行继承代理,比如我要给UserService生成一个动态代理对象,那实际上你生成代理对象,是

UserService这个对象的子类,它会把被代理对象进行一个继承,对他进行一个继承,那我们还记得hibernate,

当中有一个细节不知道你们记不记得,就是hibernate实体有一个要求,就是咱们的实体要求最好使用包装类型,

是类不能被final修饰,其实hibernate在产生代理对象的时候,先不查,先产生代理对象,那个时候就是cglib代理,

那你现在理解hibernate,他对要求在类上不能使用final了,明白啥意思不,这不是出来不了吗,cglib代理,他的

代理原理是对目标继承代理,那如果这个被代理对象,如果他是被final修饰,那就无法被继承,这样的话就生成

不了代理了,如果目标对象被final修饰,该类无法被cglib代理,那这样的话,Spring同时整合了两个代理技术,

那有人说Spring到底是使用哪一种代理对象呢,混合的,没错,啥叫混合式,他如果有接口,优先使用,如果发现

要你代理的这个对象,没有接口,他就会使用cglib代理,所以这块的话,Spring他支持了这两种,然后接下来这样

使用动态代理和cglib代理,分别完成对类的代理功能,而我们要手动来完成这两种方式来做代理,

咱们做一下准备工作,c_proxy,service包,给后面两节课做一个例子铺垫,UserService是咱们的interface,

delete,update,然后find,声明一个UserService接口,接下来再创建一个实现类,UserServiceImpl,实现咱们的

UserService接口,然后实现这个四个方法
package com.learn.service;

public interface UserService {

	void save();
	
	void delete();
	
	void update();
	
	void find();
}
这个四个方法的实现全都是非常简单的实现,咱们写了UserService的一个实现类了,里面的四个方法,

然后接下来呢,要写的代码,这里是Service的方法,咱们要对这些方法进行事务管理,如果真正是项目代码的话,

我就打开事务,保存完用户之后,提交事务,是这个意思不,那我用了四个方法,是不是每个方法都要写,我用动态

代理技术,分别对我们这个实现类进行代理,然后来增强这四个方法,把事务管理代码,插入到这四块当中,明白啥

意思不,这个就是咱们要写动态代码的目的,手动来完成代理,接下里再新建一个包
package com.learn.service;

public class UserServiceImpl implements UserService {

	@Override
	public void save() {
		System.out.println("保存用户!");
	}

	@Override
	public void delete() {
		System.out.println("删除用户!");
	}

	@Override
	public void update() {
		System.out.println("更新用户!");
	}

	@Override
	public void find() {
		System.out.println("查找用户");
	}

}
就叫proxy,第一个UserServiceProxyFactory,UserService的代理工厂,那这个动态代理的工厂当中,

有一个工厂方法,然后返回UserService对象,getUserServiceProxy,然后在这个方法里面,你去调这个方法,

返回一个UserService的一个代理对象,然后在这里面生成动态代理返回,那生成动态代理的话,调用Proxy.newInstance,

第一个叫类加载器,类加载器学过吧,随便给个数都可以,第二个参数把接口给他,接口的话就是被代理对象,UserServiceImpl,

是不是他,被代理对象,点class点getInterfaces,获得被代理对象的实现类接口,传给第二个参数,第三个参数是啥玩意呢,

第三个参数很关键,第三个参数是咱们指定,代理到底要怎么增强,增强的内容,要求你传入的接口,InvocationHandler,

那这个接口的话,我打算这样,让本身这个Factory去实现这个接口,Factory去实现这个,让本身去实现的话那就好写了,

我本身去实现这个接口的话,是不是用InvocationHandler,这里是不是接收一下,这里是不是就是咱们的UserService,

咱们叫usProxy对象,然后强转成UserService对象,return usProxy,这样getUserProxy方法就讲完了,主要把这个接口实现

就完事了,这里面三个参数,分别会把当前的代理对象传进来,会把当前调用的方法传进来,方法执行的方法参数传进来,

那以前的方法该调还得调,这是代表你现在执行的业务方法,这个方法你该调还得调,所以这里调用一下invoke方法,

这里把方法值传进去,但是这里知道,咱们的invoke方法,是不是需要方法所在对象的,也来一个实例,这个实例他哪里来呢,

这块的话,产生代理的话,得需要你给我传进来啊,哪个类执行这个方法,就执行代理,所以你得把这个类给我传进来,

所以我在这里使用构造方法,要他必须把这个us给我传进来,那咱们就把us作为咱们运行所在的类,这个结果的话,

return出去,这个就是业务方法的执行了,是不是在执行之前,咱们不是说要打开事务吗,然后业务方法执行之后,

是不是要提交事务,这样看我们这个接口实现类就写完了,这两行就是咱们要生成的代码,这一行是原有方法的调用,

接下来咱们试一下,咱们动态代理方法的写完,写一个Demo测试一下,看他是不是增强了,public void fun1()
这是被代理对象的,创建咱们的factory,factory等于,new一个UserServiceProxyFactory,

然后传进去以后,咱们只需要调用getUserServiceFactory方法,咱们的代理对象叫usProxy,

调用usProxy的如何增加方法
package com.learn.c_proxy;

import org.junit.Test;

import com.learn.service.UserService;
import com.learn.service.UserServiceImpl;

public class Demo {
	
	@Test
	public void fun1() {
		UserService us = new UserServiceImpl();
		
		UserServiceProxyFactory factory = new UserServiceProxyFactory(us);
		
		UserService usProxy = factory.getUserServiceProxy();
		
		usProxy.save();
			
	}

}
打开事务
保存用户!
提交事务
是不是这个效果,保存用户之前,之后,你看动态代理是不是这样演示的,也是这样演示吧,差不多吧,

你要学会怎么去配,不会让你自己手写的,这是使用动态代理手动来完成代理对象,来增强咱们的目标方法

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值