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();
}
}