静态代理和动态代理

一.AOP的概念
1.概念:AOP即面向切面编程,与OOP(面向对象编程)相辅相成。即将程序中重复代码抽取出来,在程序执行时利用动态代理技术,运用这些代码。
OOP中程序的基本单元是类,AOP中程序的基本单元是切面
2.优势
减少代码重复、维护方便、提高开发效率
3.AOP术语
(1)切面:切入点+通知
(2)连接点:目标对象中有可能被增强的方法。目标对象中所有的方法都是连接点
(3)切入点:目标对象中已经被增强的方法
(4)通知:增强的代码
(5)代理:将通知织入到目标对象中形成代理对象
(6)目标对象:被代理的对象
(7)织入:将通知应用到切入点的过程
4.实现方式
jdk动态代理+cglib动态代理
二.代理模式
目标类和代理类要有相同的行为,代理对象对目标对象的功能进行增强
代理模式中的角色有:

  • 业务接口:目标类和代理类共同去实现的
  • 目标类:业务逻辑的具体执行者
  • 代理类:对目标类的功能进行增强
  • 测试类:通过访问代理类中的方法,就可访问到所有方法

三.静态代理
特点:在运行之前创建代理类,通过代理类产生代理对象。目标类和代理类实现同一接口。
静态代理例子
观众去看演唱会,其中布置舞台和卖票都由经纪公司去实现,而唱歌跳舞由歌手实现。这就是静态代理,公司是代理类,歌手是目标类,他们共同实现的是完成演出。
业务接口:

//业务接口
public interface Show {
	public void show();
}

目标类:

//目标类
@Data
@AllArgsConstructor
public class Singer implements Show{
	private String name;
	@Override
	public void show() {
		System.out.println(this.name+":唱歌");
		System.out.println(this.name+":跳舞");		
	}
}

@AllArgsConstructor:使用此注解相当于直接构造该类的有参构造器

代理类:

//代理类
@Data
@AllArgsConstructor
public class Company implements Show{
	private String name;
	//代理的目标对象
	private Show target;
	@Override
	public void show() {
		System.out.println(this.name+":布置");
		System.out.println(this.name+":卖票");
		target.show();	
	}
}

测试类:

//测试类
public class User {
	public static void main(String[] args) {
		Show target = new Singer("偶像");
		Show proxy = new Company("经纪公司",target);
		proxy.show();
	}
}

四.动态代理
1.JDK动态代理
特点:在程序运行中产生一个代理类,并通过该类产生代理对象。
(1)动态代理借助java.lang.reflect.Proxy类,调用该类的newProxyInstance()方法自动生成代理类。
newProxyInstance(loader,Interface,InvocationHandler):
三个参数分别是:

  • 目标类的类加载器,用于加载代理类
  • 目标类实现的接口,用于给代理类实现
  • InvocationHandler的实例

(2)通过实现java.lang.reflect.InvocationHandler接口的唯一方法invoke()来处理代理类的方法
invoke(proxy,nethod,args)

  • proxy:产生的代理对象
  • method:目标类中的方法
  • args:目标对象的方法中的参数

动态代理实现上述静态代理的例子:
业务接口和目标类同上

方法一:

业务处理类:

//业务处理类
@AllArgsConstructor
public class HandlerImpl implements InvocationHandler{
	private Singer singer;
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println("经纪公司:布景");
		System.out.println("经纪公司:卖票");
		Object result = method.invoke(singer, args);
		System.out.println("经纪公司:收拾");
		return result;
	}
}

测试类:

//测试类
public class User {
	public static void main(String[] args) {
		//创建目标对象
		Singer singer = new Singer("偶像");
		//创建业务处理对象
		HandlerImpl handler = new HandlerImpl(singer);
		//创建代理对象
		Show proxy = (Show)Proxy.newProxyInstance(
				//目标对象的类加载器
				Singer.class.getClassLoader(), 
				//目标对象实现的接口
				Singer.class.getInterfaces(), 
				//业务处理类的实例
				handler);				
		proxy.show();
	}
}

@AllArgsConstructor:该注解意味着创建了有参构造器

方法二:匿名内部类写法

//测试类
public class User {
	public static void main(String[] args) {
		//创建目标对象
		Singer singer = new Singer("偶像");
		//创建代理对象
		Show proxy = (Show)Proxy.newProxyInstance(
				//目标对象的类加载器
				Singer.class.getClassLoader(), 
				//目标对象实现的接口
				Singer.class.getInterfaces(), 
				new InvocationHandler() {
					@Override
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						System.out.println("经纪公司:布景");
						System.out.println("经纪公司:卖票");
						//通过反射的方式调用目标对象中的方法,并接收执行结果
						Object object = method.invoke(singer, args);
						System.out.println("经纪公司:收尾");
						return object;
					}
				});
		proxy.show();
	}
}

当代理对象执行方法的时候,invoke()才能被执行

在这里插入图片描述

2.cglib动态代理
jdk动态代理必须实现接口,对于没有实现接口的目标类,只能采用cglib动态代理。
实现原理:目标类是父类,代理类是子类。代理类继承了目标类,重写了目标类中的方法。代理对象在调用目标方法时,实际调用的是重写的方法intercept()

asm包和cglib包可能因为版本不兼容报错,可直接用spring-core包,这里已经继承了cglib所需的jar包

(1)MethodInterceptor接口,重写该接口的intercept()方法。该方法会在代理对象执行目标方法时被调用
intercept(Object proxy,Method method,Object args,MethodProxy methodProxy)

  • proxy:cgllib根据指定的父类产生的代理对象
  • method:目标对象中的方法
  • args:方法参数
  • methodProxy:方法的代理对象,用于执行父类的方法

invokeSuper(proxy,args)
调用该方法即调用的是proxy类的父类的方法
(2)Enhancer类相当于jdk中的Proxy类,都是用来生成代理对象的。
Enhancer类的create()用来创建代理对象

目标类:

//目标类
@AllArgsConstructor
public class Student {
	public void saveAnddelete() {
		System.out.println("执行保存学生操作");
		System.out.println("执行删除学生操作");
	}	

方法拦截器:

//方法拦截器
public class CglibProxy implements MethodInterceptor{
	@Override
	public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
		System.out.println("开启事务");
		//调用目标类中的目标方法
		Object obj = methodProxy.invokeSuper(proxy, args);
		System.out.println("关闭事务");
		return obj;
	}
}

测试类:

//测试类
public class Test {
	public static void main(String[] args) {
		//创建增强类对象,相当于jdk中的代理类
		Enhancer enhancer = new Enhancer();
		//设置代理类的父类
		enhancer.setSuperclass(Student.class);
		//设置回调对象
		enhancer.setCallback(new CglibProxy());		
		//creat()方法是创建代理对象
		Student proxy = (Student)enhancer.create();
		proxy.saveAnddelete();		
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值