SpringAOP的实现机制

设计模式代理模式

参考我之前的代理模式

http://www.cnblogs.com/cutter-point/p/5226642.html

这里写个简单的案例

package spring.aop.designPattern;

/**
*
* Title: ISubject.java
* Description:代理模式的资源接口类
* @author xiaof
* @date 2018年4月7日
* @version 1.0
*
*/
public interface ISubject { public void request();
}
package spring.aop.designPattern;

/**
*
* Title: SubjectImpl.java
* Description: 被访问者,或者被访问的资源实现类
* @author xiaof
* @date 2018年4月7日
* @version 1.0
*
*/
public class SubjectImpl implements ISubject { @Override
public void request() {
// TODO Auto-generated method stub
System.out.println("this is subjectImpl cutter_point ! ");
} }
package spring.aop.designPattern;

/**
*
* Title: SubjectProxy.java
* Description: 代理实现类
* @author xiaof
* @date 2018年4月7日
* @version 1.0
*
*/
public class SubjectProxy implements ISubject { private ISubject subject; @Override
public void request() {
System.out.println("pre operation subjectproxy");
if(subject != null)
subject.request(); System.out.println("after operation subjectproxy");
} public ISubject getSubject() {
return subject;
} public void setSubject(ISubject subject) {
this.subject = subject;
} }
package spring.aop.designPattern;

import org.junit.Test;

public class Main {

    @Test
public void test1() {
SubjectImpl si = new SubjectImpl();
SubjectProxy sp = new SubjectProxy();
sp.setSubject(si); sp.request();
}
}

测试一波:

【sping揭秘】12、SpringAOP的实现机制-LMLPHP

这就是,比如我们要对subjectimpl进行代理的时候,我们就需要根据ISubject接口实现一个代理类对象

好,基于此点,

缺点1:如果我们一个类不存在接口类型,并且是第三方的类对象,比如我们现在有一个subjectimpl2,这个类没有实现ISubject接口,那么我们的subjectimpl还能进行代理吗?显然是不能的

缺点2:我们发现对一个subjectimpl对象进行代理就要实现一个代理类subjectProxy,那如果我们项目用有一个万类对象需要进行代理,那么我们需要创建一万个proxy类,好吧,我反正会疯的。。。

动态代理

这个jdk的动态代理主要是,proxy类和invocationhandler接口

package spring.aop.designPattern;

/**
*
* Title: ISubject.java
* Description:代理模式的资源接口类
* @author xiaof
* @date 2018年4月7日
* @version 1.0
*
*/
public interface ISubject { public void request();
}
package spring.aop.designPattern;

/**
*
* Title: SubjectImpl.java
* Description: 被访问者,或者被访问的资源实现类
* @author xiaof
* @date 2018年4月7日
* @version 1.0
*
*/
public class SubjectImpl implements ISubject { @Override
public void request() {
// TODO Auto-generated method stub
System.out.println("this is subjectImpl cutter_point ! ");
} }

代理类

package spring.aop.dynamicPorxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Date; import spring.aop.util.DateUtil; /**
*
* Title: RequestCtrlInvocationHandler.java
* Description: jdk动态代理对象
* @author xiaof
* @date 2018年4月7日
* @version 1.0
*
*/
public class RequestCtrlInvocationHandler implements InvocationHandler { /**
* 代理对象
*/
private Object target;
/**
* 00:00:00
*/
private String beginTime;
/**
* 00:00:00
*/
private String endTime; public RequestCtrlInvocationHandler(Object target, String beginTime, String endTime) {
this.target = target;
this.beginTime = beginTime;
this.endTime = endTime;
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//判断是否是request方法,如果是进行拦截操作
if(method.getName().equals("request")) {
//判断当前时间是否在区间内,如果是,那么就进行相应的操作
if(DateUtil.isInDate(new Date(), beginTime, endTime)) {
System.out.println("区间内时间,拦截成功");
return method.invoke(target, args);
} else {
System.err.println("区间外时间");
return null;
}
}
return method.invoke(target, args);
} }

最后测试:

目前时间!

【sping揭秘】12、SpringAOP的实现机制-LMLPHP

那么我们修改时间区间,看是否会产生不一样的后果!!!

0-12点

【sping揭秘】12、SpringAOP的实现机制-LMLPHP

【sping揭秘】12、SpringAOP的实现机制-LMLPHP

那么我们把时间改为22点呢

【sping揭秘】12、SpringAOP的实现机制-LMLPHP

拦截成功

不多BB,这个还是有问题,无法处理接口类问题

动态字节码生成

使用cblib

package spring.aop.cglib;

import java.lang.reflect.Method;
import java.util.Date; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy; import spring.aop.util.DateUtil; /**
*
* Title: RequestCtrlCallback.java
* Description: 动态字节码技术
* @author xiaof
* @date 2018年4月7日
* @version 1.0
*
*/
public class RequestCtrlCallback implements MethodInterceptor { private static final Log logger = LogFactory.getLog(RequestCtrlCallback.class); /**
* 00:00:00
*/
private String beginTime;
/**
* 00:00:00
*/
private String endTime; public RequestCtrlCallback(String beginTime, String endTime) {
this.beginTime = beginTime;
this.endTime = endTime;
} @Override
public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable { //如果是我们需要拦截的方法,那么进行相应的操作
if(arg1.getName().equals("request")) {
if(DateUtil.isInDate(new Date(), beginTime, endTime)) {
//在对应的时间区间内,成功
logger.info("成功拦截到对应的区间,放行!");
return arg3.invokeSuper(arg0, arg2);
} else {
logger.error("错误时间区间!!");
return null;
}
} return arg3.invokeSuper(arg0, arg2); } public String getBeginTime() {
return beginTime;
} public void setBeginTime(String beginTime) {
this.beginTime = beginTime;
} public String getEndTime() {
return endTime;
} public void setEndTime(String endTime) {
this.endTime = endTime;
} }
package spring.aop.cglib;

import org.junit.Test;
import org.springframework.cglib.proxy.Enhancer; import spring.aop.designPattern.SubjectImpl; public class Main { @Test
public void test1() {
//使用cglib代理对象
String beginTime = "00:00:00";
String endTime = "20:00:00";
Enhancer enhancer = new Enhancer();
//设置代理类对象
enhancer.setSuperclass(SubjectImpl.class); enhancer.setCallback(new RequestCtrlCallback(beginTime, endTime)); //生成代理对象
SubjectImpl proxyObj = (SubjectImpl) enhancer.create(); proxyObj.request();
}
}

结果展示:

【sping揭秘】12、SpringAOP的实现机制-LMLPHP

【sping揭秘】12、SpringAOP的实现机制-LMLPHP

05-20 04:08
查看更多