平常开发中的日志、权限、事务处理等。
代理模式实现原理图
代理模式:是经常使用的java设计模式,他的特点是代理类与拜托类有一样的接口,代理类主要负责为拜托类预处理消息、过滤消息、把消息转发给拜托类,和事后处理消息等。代理类与拜托类之间通常会存在关联关系,1个代理类的对象与1个拜托类的对象关联,代理类的对象本身其实不真正实现服务,而是通过调用拜托类的对象的相干方法,来提供特定的服务。
依照代理的创建时期,代理类可以分为两种。
静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已存在了。
动态代理:在程序运行时,应用反射机制动态创建而成。
1.抽象目标类
public interface Subject(){
public void Request();
}
2.具体目标类
public class RealSubject implements Subject(){
public void Request(){
};
}
3.代理类
public class Proxy (){
private RealSubject realSubject;
public void Request(){
/**附加逻辑**/
realSubject.Request();
/**附加逻辑**/
};
}
JDK动态的代理的3个主要类:
Proxy:代理类
InvocationHandler: 接口
Method:要被调用的方法
TaxInterface.java
public interface TaxInterface {
public void doTax();
}
Tax.java
public class Tax implements TaxInterface{
@Override
public void doTax() {
System.out.println("进行所得税计算的逻辑处理");
}
}
TimeProxy.java
public class TimeProxy implements InvocationHandler{
private Object obj;
//绑定代理对象
public Object bind(Object obj){
this.obj = obj;
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
}
//实现代理
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result = null;
try {
long startTime = System.nanoTime();
result = method.invoke(obj, args);
long endTime = System.nanoTime();
System.out.println("计算程序运行时间 :" +(endTime-startTime));
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
}
客户端测试:Client.java
public class Client {
public static void main(String[] args) {
TimeProxy timeProxy = new TimeProxy();
TaxInterface taxInterface = (TaxInterface)timeProxy.bind(new Tax());
taxInterface.doTax();
}
}
JDK的动态代理依托接口实现,如果有些类并没有实现接口,则不能使用JDK代理,这就要使用cglib动态代理了。
JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成1个子类,并覆盖其中方法实现增强,但由于采取的是继承,所以不能对final修饰的类进行代理。
示例以下:
BookFacadeCglib.java
package com.ldw.dao;
public interface BookFacade {
public void addBook();
}
BookCadeImpl1.java
package com.ldw.dao.impl;
/**
* 这个是没有实现接口的实现类
*
* @author csu.ldw
*
*/
public class BookFacadeImpl1 {
public void addBook() {
System.out.println("增加图书的普通方法...");
}
}
BookFacadeProxy.java
package com.ldw.proxy;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/**
* 使用cglib动态代理
*
* @author student
*
*/
public class BookFacadeCglib implements MethodInterceptor {
private Object target;
/**
* 创建代理对象
*
* @param target
* @return
*/
public Object getInstance(Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
// 回调方法
enhancer.setCallback(this);
// 创建代理对象
return enhancer.create();
}
@Override
// 回调方法
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
System.out.println("事物开始");
proxy.invokeSuper(obj, args);
System.out.println("事物结束");
return null;
}
}
TestCglib.java
package com.ldw.test;
import net.battier.dao.impl.BookFacadeImpl1;
import net.battier.proxy.BookFacadeCglib;
public class TestCglib {
public static void main(String[] args) {
BookFacadeCglib cglib=new BookFacadeCglib();
BookFacadeImpl1 bookCglib=(BookFacadeImpl1)cglib.getInstance(new BookFacadeImpl1());
bookCglib.addBook();
}
}
SpringAOP、Struts拦截器、日志管理等。
struts2的拦截器属于AOP思想,采取了代理模式
struts2中,最重要的1个类是org.apache.struts2.dispatcher.FilterDispatcher用户通过阅读器提交1个HttpServletRequest要求后,要求被在web.xml中的过滤器FilterDispatcher拦截在FilterDispatcher过滤器中首先询问ActionMapper是不是需要调用某个Action来处理要求,如果ActionMapper决定需要调用某个要求,FilterDispatcher则把要求的处理交给ActionProxy,ActionProxy通过配置文件struts.xml找到需要调用的Action类,然后ActionProxy创建1个ActionInvocation实例并通用该Action但在调用之前,ActionInvocation会根据配置加载Action相干的Intercepter,等Action履行终了,ActionInvocation负责根据struts.xml中的配置找到对应的Result结果。