java动态代理
来源:互联网 发布:淘宝换货 先确认收货 编辑:程序博客网 时间:2024/06/15 10:43
1.JDK代理
动态的由java提供的api在内存中构建字节码类对象完成的动态代理.
使用JDK代理方式动态创建对象时,对象需要声明接口并且实现接口;
1.1声明接口:
package yzr.dyn_jdk;public interface IPerson {void SayHello();}1.2 声明对象,并且实现接口:
package yzr.dyn_jdk;public class PersonImpl implements IPerson {private String name;@Overridepublic void SayHello() {System.out.println("Hello "+this.name);}public PersonImpl(){}public PersonImpl(String name){this.name=name;}}1.3实现自己的InvocationHandler类
package yzr.dyn_jdk;import java.lang.reflect.InvocationHandler;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;public class MyInvocationHandler implements InvocationHandler {private Object target;public MyInvocationHandler(){super();}public MyInvocationHandler(Object target){super();this.target=target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args){Object Result=null;try {Result=method.invoke(target, args);} catch (Exception e) {e.printStackTrace();} return Result;}}1.4得到代理对象并且调用
package yzr.dyn_jdk;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy; public class TestUnit {public static void main(String[] args) {IPerson LYF=new PersonImpl("yzr");InvocationHandler handler=new MyInvocationHandler(LYF);IPerson LYFProxy = (IPerson)Proxy.newProxyInstance(LYF.getClass().getClassLoader(), LYF.getClass().getInterfaces(),handler); LYFProxy.SayHello();}}使用JDK代理的方式动态创建对象时,和使用new关键字(或者反射)创建对象的不同在于,调用对象的方法的时候,可以加入额外的逻辑代码,比如:
@Overridepublic Object invoke(Object proxy, Method method, Object[] args){Object Result=null;try {System.out.println("调用方法之前:");Result=method.invoke(target, args);System.out.println("调用方法之后:");} catch (Exception e) {e.printStackTrace();} return Result;}但是不方便的地方是使用JDK代理这方式要求声明接口,实现接口的对象才能被动态代理生成,所以下面使用cglib代理动态创建对象:
2.cglib代理
需要三个jar包: asm-3.3.1.jar cglib-2.2.jar cglib-nodep-2.2.jar
2.1声明对象
package yzr.dyn_cglib;public class PersonImpl {private String name;public void SayHello() {System.out.println("Hello "+this.name);}public PersonImpl(){}public PersonImpl(String name){this.name=name;}}2.2 实现MethodInterceptor接口
package yzr.dyn_cglib;import java.lang.reflect.Method;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;public class CglibProxy implements MethodInterceptor {@Overridepublic Object intercept(Object arg0, Method arg1, Object[] arg2,MethodProxy arg3) throws Throwable {System.out.println(arg1.getName()); System.out.println("调用方法之前");Object result=arg3.invokeSuper(arg0, arg2);System.out.println("调用方法之之后");return result;}}2.3动态获取对象
package yzr.dyn_cglib;import yzr.dyn_jdk.PersonImpl;import net.sf.cglib.proxy.Enhancer;public class CglibUnit {public static void main(String[] args) {CglibProxy proxy=new CglibProxy();Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(PersonImpl.class); enhancer.setCallback(proxy); PersonImpl per = (PersonImpl)enhancer.create(); per.SayHello();}}
像这样的方式就可以不要求一定需要声明接口就可以动态代理,但是不管是JDK代理或者CgLib代理,都需要事先声明PersonImpl实体类,就是说被动态创建的对象都需要声明好,假如说如果不想手动声明这样的一个实体类(被动态创建的对象),又或者说即使是声明了类似于PersonImpl这样的实体对象,但需要能够动态的为它新增一些新的属性并且赋值,这些想法都可以实现.,下面说一下该怎么做:
3.动态代理
一个动态Bean,读取属性文件内容作为被创建对象的属性,当然你也可以选择不使用属性文件,直接写在代码上也可以;
package yzr.dynamiceBean;import java.util.Iterator;import java.util.Map;import java.util.Set;import net.sf.cglib.beans.BeanGenerator;import net.sf.cglib.beans.BeanMap;public class DynamicBean { private Object object = null;//动态生成的类 private BeanMap beanMap = null;//存放属性名称以及属性的类型 public DynamicBean() { super(); } public DynamicBean(Map propertyMap) { this.object = generateBean(propertyMap); this.beanMap = BeanMap.create(this.object); } public void setValue(Object property, Object value) { beanMap.put(property, value); } public Object getValue(String property) { return beanMap.get(property); } public Object getObject() { return this.object; } private Object generateBean(Map propertyMap) { BeanGenerator generator = new BeanGenerator(); Set keySet = propertyMap.keySet(); for (Iterator i = keySet.iterator(); i.hasNext();) { String key = (String) i.next(); generator.addProperty(key, (Class) propertyMap.get(key)); } return generator.create();}}
package yzr.dynamiceBean;import java.beans.BeanInfo;import java.beans.Introspector;import java.beans.PropertyDescriptor;import java.io.InputStream;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.util.HashMap;import java.util.Iterator;import java.util.Properties;import java.util.Set;public class ClassUtil {public Object dynamicClass(Object object) throws Exception {HashMap returnMap = new HashMap();HashMap typeMap = new HashMap();// 读取配置文件Properties prop = new Properties();String sourcepackage = object.getClass().getName();String classname = sourcepackage.substring(sourcepackage.lastIndexOf(".") + 1);InputStream in = ClassUtil.class.getResourceAsStream("/Dynamic.properties");prop.load(in);Set<String> keylist = prop.stringPropertyNames();Class type = object.getClass();BeanInfo beanInfo = Introspector.getBeanInfo(type);PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();//添加自身属性for (int i = 0; i < propertyDescriptors.length; i++) {PropertyDescriptor descriptor = propertyDescriptors[i];String propertyName = descriptor.getName();if (!propertyName.equals("class")) {Method readMethod = descriptor.getReadMethod();Object result = readMethod.invoke(object, new Object[0]);if (result != null) {returnMap.put(propertyName, result);} else {returnMap.put(propertyName, "");}typeMap.put(propertyName, descriptor.getPropertyType());}}// 加载配置文件中的属性Iterator<String> iterator = keylist.iterator();while (iterator.hasNext()) {String key = iterator.next();returnMap.put(key, prop.getProperty(key));typeMap.put(key, Class.forName("java.lang.String"));}// map转换成实体对象DynamicBean bean = new DynamicBean(typeMap);// 赋值Set keys = typeMap.keySet();for (Iterator it = keys.iterator(); it.hasNext();) {String key=it.next().toString();bean.setValue(key, returnMap.get(key));}Object obj = bean.getObject();return obj;}public static void main(String[] args) throws Exception {Object object = new ClassUtil().dynamicClass(new Object());Class c = object.getClass();Method[] methods = c.getDeclaredMethods();// 得到方法Field[] fs = c.getDeclaredFields();for (int i = 0; i < fs.length; i++) {Field f = fs[i];f.setAccessible(true); // 设置些属性是可以访问的Object val = f.get(object);// 得到此属性的值String type = f.getType().toString();// 得到此属性的类型System.out.println("type=" + type + "\t name:" + f.getName()+ "\t value = " + val);}}}
属性文件Dynamic.properties:
name=YZR;
运行结果:
被动态创建对象中的属性会带有$cglib_prop前缀;
案例代码下载:点击下载案例
1 0
- Java 代理,动态代理
- [Java] Java 动态代理
- java代理及动态代理
- java代理模式--动态代理
- Java静态代理、动态代理
- Java 代理之 动态代理
- Java 代理与动态代理
- java静态代理,动态代理
- 代理模式&java动态代理
- Java代理与动态代理
- Java静态代理动态代理
- JAVA代理模式--动态代理
- java 代理和动态代理
- JAVA动态代理 代理模式
- Java动态代理--jdk代理
- Java动态代理--cglib代理
- Java 代理与动态代理
- java代理模式-动态代理
- STOMP Protocol
- C++抽象编程——字符串(3)——字符串判断与大小写转换
- 客户端即(浏览器端的用户机器上)为什么还要装jre?
- LeakCanary使用说明
- android 7.0 获取相机问题
- java动态代理
- 哈希 — 康托展开
- java数组
- fragment与activity及两个fragment之间的跳转实现
- HTML5 移动页面自适应手机屏幕四类方法
- 自定义Dialog宽度无法全屏的解决方案
- mysql中文查询不到结果
- 运算符的优先级
- HDU 1213 How Many Tables