这里,介绍两种非注解的动态代理:一种是JDK动态代理,使用的是java.lang.reflect
包中的InvocationHandler、Method和Proxy;另一种是CGlib动态代理:需要Spring
包中的,cglib-nodep.jar文件。
一.JDK动态代理
注意:JDK动态代理的对象,必须实现接口。
package com.zyy.service;
/**
* Created by CaMnter on 2014/8/20.
*/
public interface PersonService_3 {
public void save(String name);
public void update(Integer personId, String name);
public void delete(Integer personId);
}
package com.zyy.service.impl;
import com.zyy.service.PersonService_3;
/**
* Created by CaMnter on 2014/8/21.
*/
/**
* JDKProxyFactory 代理的对象 要求实现接口
*/
/*
* 1.拦截所有的业务方法
* 2.判断用户是否有权限
* 3.有权限则允许他执行业务方法,没权限则不允许(这里根据user是否为null作为判断)
*/
public class PersonServiceBean_3 implements PersonService_3 {
private String user = null;
public String getUser() {
return user;
}
public PersonServiceBean_3() {
}
public PersonServiceBean_3(String user) {
this.user = user;
}
public void save(String name) {
System.out.println("***** save " + name + " *****");
}
public void update(Integer personId, String name) {
System.out.println("***** update *****");
}
public void delete(Integer personId) {
System.out.println("***** delete *****");
}
}
package com.zyy.aop;
import com.zyy.service.impl.PersonServiceBean_3;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* Created by CaMnter on 2014/8/21.
*/
/**
* JDK的动态代理
* <p/>
* 但是要求目标对象实现接口,因为
* Proxy.newProxyInstance(this.targetObject.getClass().getClassLoader(),
* this.targetObject.getClass().getInterfaces(), this);
*/
/*
*
* 当用户调用代理对象
* 代理对象调用invoke
* 判断权限(if)
* 然后invoke方法中再委派给目标对象
* (Object result = method.invoke(this.targetObject,args) ;)
*
*/
public class JDKProxyFactory implements InvocationHandler {
//代理的目标对象
private Object targetObject;
public Object createProxyInstance(Object targetObject) {
this.targetObject = targetObject;
/*
* 第一个参数设置代码使用的类装载器,一般采用跟目标类相同的类装载器
* 第二个参数设置代理类实现的接口
* 第三个参数设置回调对象,当代理对象的方法被调用时,会委派给该参数指定对象的invoke方法
*/
return Proxy.newProxyInstance(this.targetObject.getClass().getClassLoader(),
this.targetObject.getClass().getInterfaces(), this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
PersonServiceBean_3 bean = (PersonServiceBean_3) this.targetObject;
Object result = null;
//权限过滤 代理对象有 user的值 才能调用它的方法
if (bean.getUser() != null) {
result = method.invoke(this.targetObject, args);
}
return result;
}
}
junit4.4.测试代码:
@Test
public void jdkproxyTest() {
//JDK动态代理
JDKProxyFactory jdkProxyFactory = new JDKProxyFactory();
System.out.println("***** JDK动态代理 *****");
System.out.println("***** 没有user值实例化目标 *****");
PersonService_3 personService_3 = (PersonService_3) jdkProxyFactory.createProxyInstance(new PersonServiceBean_3());
System.out.println("----- 无法调用方法 -----");
personService_3.save("07");
System.out.println("***** 有user值实例化目标 *****");
personService_3 = (PersonService_3) jdkProxyFactory.createProxyInstance(new PersonServiceBean_3("CaMnter"));
System.out.println("----- 可以调用方法 -----");
personService_3.save("07");
}
没有user值实例化目标,就在JDK代理那里过滤掉了,就无法使用方法。
二.CGlib动态代理
目标不需要接口,但是实现CBlib代理需要Spring 的依赖包cglib-nodep.jar。
package com.zyy.service.impl;
/**
* Created by CaMnter on 2014/8/21.
*/
/**
* CGlibProxyFactory 代理的对象 不要求实现接口
*/
/*
*
* 1.拦截所有的业务方法
* 2.判断用户是否有权限
* 3.有权限则允许他执行业务方法,没权限则不允许(这里根据user是否为null作为判断)
*/
public class PersonServiceBean_4 {
private String user = null;
public String getUser() {
return user;
}
public PersonServiceBean_4() {
}
public PersonServiceBean_4(String user) {
this.user = user;
}
public void save(String name) {
System.out.println("***** save " + name + " *****");
}
public void update(Integer personId, String name) {
System.out.println("***** update *****");
}
public void delete(Integer personId) {
System.out.println("***** delete *****");
}
}
package com.zyy.aop;
/**
* Created by CaMnter on 2014/8/21.
*/
import com.zyy.service.impl.PersonServiceBean_4;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* CGllib的动态代理
*/
/*
*
* 当用户调用代理对象
* 代理对象调用invoke
* 判断权限(if)
* 然后invoke方法中再委派给目标对象
* (Object result = method.invoke(this.targetObject,args) ;)
*
*/
public class CGlibProxyFactory implements MethodInterceptor {
private Object targetObject;
public Object createProxyInstance(Object targetObject) {
this.targetObject = targetObject;
//CGlib代理
Enhancer enhancer = new Enhancer();
//CGlib代理 就是继承了目标类 ,对目标类中所用非final 的进行覆盖
enhancer.setSuperclass(this.targetObject.getClass());
//当被目标类调用的时候
enhancer.setCallback(this);
return enhancer.create();
}
public Object intercept(Object o, Method method,
Object[] objects, MethodProxy methodProxy) throws Throwable {
PersonServiceBean_4 bean = (PersonServiceBean_4) this.targetObject;
Object result = null;
//权限过滤 代理对象有 user的值 才能调用它的方法
if (bean.getUser() != null) {
result = method.invoke(this.targetObject, objects);
}
return result;
}
}
junit4.4测试代码:
@Test
public void cglibproxyTest() {
//CGlib动态代理
CGlibProxyFactory cGlibProxyFactory = new CGlibProxyFactory();
System.out.println("***** CGlib动态代理 *****");
System.out.println("***** 没有user值实例化目标 *****");
PersonServiceBean_4 personServiceBean_4 = (PersonServiceBean_4) cGlibProxyFactory.createProxyInstance(new PersonServiceBean_4());
System.out.println("----- 无法调用方法 -----");
personServiceBean_4.save("07");
System.out.println("***** 有user值实例化目标 *****");
personServiceBean_4 = (PersonServiceBean_4) cGlibProxyFactory.createProxyInstance(new PersonServiceBean_4("CaMnter"));
System.out.println("----- 可以调用方法 -----");
personServiceBean_4.save("07");
}
没有user值实例化目标,就在CGlib代理那里过滤掉了,就无法使用方法。