代理模式:静态代理;JDK动态代理;cglib动态代理

eg:加减乘除
1.新建ArithmeticCalculator.java接口

public interface ArithmeticCalculator {

	int add(int i,int j);
	int sub(int i,int j);
	int mul(int i,int j);
	int div(int i,int j);
}

2.实现类ArithmeticCalculatorLoggingImpl.java(传统)

public class ArithmeticCalculatorLoggingImpl implements ArithmeticCalculator {

	@Override
	public int add(int i, int j) {
		// TODO Auto-generated method stub
		System.out.println("method add begin with:"+i+","+j);
		int result = i + j;
		System.out.println("method add end with result :"+result);
		return result;
	}

	@Override
	public int sub(int i, int j) {
		// TODO Auto-generated method stub
		System.out.println("method sub begin with:"+i+","+j);
		int result = i-j;
		System.out.println("method sub end with result:"+result);
		return result;
	}

	@Override
	public int mul(int i, int j) {
		// TODO Auto-generated method stub
		System.out.println("method mul begin with:"+i+","+j);
		int result = i*j;
		System.out.println("method mul end with result:"+result);
		return result;
	}

	@Override
	public int div(int i, int j) {
		// TODO Auto-generated method stub
		System.out.println("method div begin with:"+i+","+j);
		int result = i/j;
		System.out.println("method div end with result:"+result);
		return result;
	}

}
存在问题
1.核心代码只有int result = i + j;为了打印日志信息,把很多非业务需求的日志写到代码中,
	原有的方法膨胀,代码量越来越高
2.打印重复日志信息,如果修改日志信息需要修改模块,增加工作量

3.测试类
public class Test1 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ArithmeticCalculator calculator = new ArithmeticCalculatorLoggingImpl();
		
		int resultAdd = calculator.add(1, 2);
		
		System.out.println(resultAdd);
	}

}
针对上诉问题使用动态代理
代理设计模式原理:使用一个代理将对象包装起来,然后用该代理对象取代原始对象,
	任何对原始对象的调用都要通过代理,代理对象决定是否以及何时将方法调用传到原始对象上
	(把原本做的事情 包装起来 代理对象去完成)

代理模式

代理模式是常用的java设计模式,它的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息,
过滤消息,把消息转发给委托类,,以及事后消息处理等。代理类与委托类之间通常会存在关联关系,
一个代理类对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,
而是通过调用委托类的对象的相关方法,来提供特定的服务
按照代理的创建时期,代理类可以分为两种
1.静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。
2.动态代理:在程序运行时,运用反射机制动态创建而成。
eg:静态代理

1.新建Count.java接口

public interface Count {
	
	public void queryCount();
}

2.实现类

public class CountImpl implements Count {

	@Override
	public void queryCount() {
		// TODO Auto-generated method stub
		System.out.println("查询账户。。。");
	}

}

3.代理类CountProxy.java

public class CountProxy implements Count {

	//定义真实对象的对象
	private Count target;
	
	//通过构造赋值
	public CountProxy(Count target) {
		super();
		this.target = target;
	}


	@Override
	public void queryCount() {
		// TODO Auto-generated method stub
		System.out.println("代理事务操作开始前");
		target.queryCount();//真实目标对象
		System.out.println("代理事务操作处理后");
	}

}

4.测试类

public class Test {
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//真实对象
		Count count = new CountImpl();
		//代理对象
		Count countProxy = new CountProxy(count);
		
		countProxy.queryCount();
	}
}

如果方法数量多时使用动态代理

动态代理
1.JDK动态代理
包含一个类和一个接口
InvocationHandler接口
public interface InvocationHandler {
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
}
	Object proxy(被代理的对象), 
	Method method(要调用的方法),
	Object[] args(方法调用时所需要的参数)

可以将InvocationHandler 接口的子类想象成一个代理的最终操作类,替换掉ProxySubject。

Proxy类:
	是专门完成代理的操作类,可以通过此类为一个或多个接口动态地代理生成实现类,此类提供类如下的操作方法;
public static Object newProxyInstance(ClassLoader paramClassLoader, Class<?>[] paramArrayOfClass, InvocationHandler paramInvocationHandler) throws IllegalArgumentException
	ClassLoader paramClassLoader, (类加载器)
	Class<?>[] paramArrayOfClass, (得到全部接口)
	InvocationHandler paramInvocationHandler(得到InvocationHandler接口的子类实例)


与静态代理类对照的是动态代理类,动态代理类的字节码在程序运行时由java反射机制生成,
无需程序员手工编写它的源代码,动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,
因为java反射机制可以生成任意类型的动态代理类。java.lang.reflect包中的Proxy类和InvocationHandler接口提供了生成动态代理类的能力

但是,JDK的动态代理依靠接口实现,如果有些类并没有实现接口,则不能使用JDK动态代理,这就要使用cglib动态代理了
eg:JDK动态代理

1.新建Book.java接口

public interface Book {
	public void addBook();
	
}

2.实现类

public class BookImpl implements Book {

	@Override
	public void addBook() {
		// TODO Auto-generated method stub
		System.out.println("add book");
	}	

}

3.代理类

public class BookProxy implements InvocationHandler {

	//接收任何类型
	private Object target;
	
	public Object bind(Object target) {
		this.target = target;
		
		return Proxy.newProxyInstance(target.getClass().getClassLoader()/*BookImpl*/, target.getClass().getInterfaces()/*Book*/, this/*BookProxy*/);
	
	}
	
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		// TODO Auto-generated method stub
		Object result = null;
		System.out.println("begin事务");
		
		result = method.invoke(target, args);
		
		System.out.println("finish事务");
		
		return null;
	}
}

4.测试类

public class Test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		BookProxy proxy = new BookProxy();
		
		Book book = (Book) proxy.bind(new BookImpl());
		
		book.addBook();
	}

}
2.Cglib 动态代理
JDK的动态代理机制智能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,
cglib是针对类来实现代理的,它的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,
但因为采用的是继承,所以不能对final修饰的类进行代理

对目标类 生成一个子类对类代理

eg
1.新建方法实现类

public class BookImpl1 {
	public void addBook() {
		System.out.println("add Book");
	}
}

2.代理类

public class BookCglibProxy implements MethodInterceptor {

	private Object target;
	
	public Object getInstance(Object target) {
		this.target = target;
		
		//增强器
		Enhancer enhancer = new  Enhancer();
		//父类
		enhancer.setSuperclass(this.target.getClass());
		//回调方法
		enhancer.setCallback(this);
		//创建对象
		return enhancer.create();
		//增强器的使用相当于JDK动态代理里的Proxy.newProxyInstance
	}
	
	
	@Override
	public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
		// TODO Auto-generated method stub
		System.out.println("before");
		proxy.invokeSuper(obj, args);//真实对象方法
		System.out.println("after");
		return null;
	}

}

3.测试类

public class Test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		BookCglibProxy cglib = new BookCglibProxy();
		//父类 对象名 = new 子类 ();向上转型
		BookImpl1 bookCglib = (BookImpl1) cglib.getInstance(new BookImpl1());
	
		bookCglib.addBook();
	}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值