基于j2se动态代理AOP实现
测试Bean
package com.wenj.services;
public interface TestBean {
public void testBean();
}
package com.wenj.servicesimpl;
import com.wenj.services.TestBean;
public class TestBeanImpl implements TestBean {
private String user;
public TestBeanImpl(){}
public TestBeanImpl(String user){
this.user = user;
}
public void testBean() {
// TODO Auto-generated method stub
System.out.println("TestBean, User: " + user);
}
public String getUser() {
return user;
}
}
AOP切面
package com.wenj.aop;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class J2seProxyFactory implements InvocationHandler{
private Object obj;
public J2seProxyFactory(Object obj){
this.obj = obj;
}
public Object createProxyInstance(){
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),
this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
TestBeanImpl tb = (TestBeanImpl)obj;
Object proxyObj = null;
if(tb.getUser() != null){
proxyObj = method.invoke(obj, args);
}
return proxyObj;
}
}
createProxyInstance()是创建代理对象的方法
invoke()为拦截点
obj对象为被代理对象
在拦截点还可以添加我们所需要的事件通知
测试
最后在jUnit测试单元添加如下测试代码:
@Test
public void testAop(){
J2seProxyFactory pf = new J2seProxyFactory(new TestBeanImpl());
TestBean tb = (TestBean)pf.createProxyInstance();
tb.testBean();
}
看以看到结果可以根据权限正常的拦截到TestBean执行方法. 如果将new TestBeanImpl()改为new TestBeanImpl(“xxx”), 拦截器也可以正常的拦截到, 并且通过权限验证
基于CgLib的AOP实现
测试Bean
package com.wenj.servicesimpl;
public class TestDAO {
private String name;
public TestDAO(){ }
public TestDAO(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void save(){
System.out.println(name + " invoke save()!");
}
}
切面
package com.wenj.aop;
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import com.wenj.servicesimpl.TestDAO;
public class CgLibProxyFactory implements MethodInterceptor{
private Object targetObj;
public CgLibProxyFactory(Object targetObj){
this.targetObj = targetObj;
}
//生成代理对象
public Object getProxyObject(){
Object proxyObj = null;
Enhancer e = new Enhancer();
e.setSuperclass(targetObj.getClass());
e.setCallback(this);
proxyObj = e.create();
return proxyObj;
}
//切入点
@Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
TestDAO td = (TestDAO)targetObj;
Object test = null;
if(null != td.getName()){
if("save" == method.getName()){
//拦截点
test = method.invoke(td, args);
System.out.println("ProxyObj invoke method save()!");//after advice()
}
}
return test;
}
}
最后在jUnit测试单元添加如下测试代码
@Test
public void testCgLibProxyFactory(){
CgLibProxyFactory cf = new CgLibProxyFactory(new TestDAO("aaa"));
TestDAO t = (TestDAO)cf.getProxyObject();
t.save();
}
结果能够正常的拦截Bean执行方法, 而且能够根据我们设定的权限来进行拦截
J2SE动态代理实现AOP有一个缺陷, 就是目标对象必须实现一个接口,
所以对于没有实现接口的Bean来说得另想方法, 这里我借助一个第三方的类库CgLib, 这样使没有实现接口的类也能实现AOP的功能