java 中的动态代理
来源:互联网 发布:mac中word选项在哪里 编辑:程序博客网 时间:2024/06/05 14:38
一直都在纠结于java 中的动态代理,说实话自己也是不太明白,前几天专门研究了这个,网上有一篇不支持转载的文章,关于java 的动态代理写的不错,特别进行记录一番
还是由场景引入吧,例如某个第三方的jar包中的某个类中的某个方法的前后加上自己的逻辑,比如日志输出,你该怎么办,因为此时提供 的是第三方的class文件,你不可能去修改别人的代码
冥思苦想,要么是继承,要么是聚合,这两种方法 假设第三方提供一个Run接口,里面有一个run方法以及它的实现类Person
public Interface Run(){
public void run();
}
public class Person implements Run(){
@Override
public void run(){
system.out.println("Person running........");
}
}
第一种,利用继承实现
public class xiaoming extends Person(){
@Override
public void run(){
LOG.info("xiaoming running before run");
super.run();
LOG.INFO("xiaoming running after run");
}
}
第二种 利用聚合实现
public class xiaohei implements Run(){
private Run person;
public xiaohei(Run person){
this.person=person;
}
@Override
public void run(){
LOG.info("xiaohei running before run");
super.run();
LOG.INFO("xiaohei running after run");
}
}
综合比较两种实现方式,那种更好呢?
显然聚合比继承更好,更灵活,没有那么多的复杂的父子关系,对于后期的维护都是很方便
其实xiaoming 和xiaohei 都是person的代理类,对person 中的方法进行加强,只不过是静态代理,很受限制,只能代理Run类型的类,其他类型则没办法
java中为此引入了动态代理
动态代理的字面意思:就是一个类的代理类是动态生成的,这个类不是提前写好的,是程序运行时生出来的,并且能够代理实现了某个接口的任何类型的类
具体关系图如下所示:|
根据上图,我们大概知道动态代理有这样一个过程:
1 根据输入的接口,通过反射机制,肯定可以获取该接口对应的方法
2 根据输入的被代理类,通过反射机制,可以获取其实现的方法
可是,在哪个地方加入某个方法前后自己加入的逻辑呢,这个在哪里实现呢?
于是对该图进行改造
我们将被代理类不是直接给了黑箱子,而是通过一个Handler来实现的,至此我们来一一对应一下java中的动态代理:
黑箱子:java中的Proxy类
handler:就是java中的invocationHandler的子类
利用Proxy的newProxyInstance的静态方法,就可以动态生成一个代理类
* 这个方法有三个参数
* 1 类加载器,将动态生成的代理类的字节码文件加载到jvm虚拟机中
* 2 被代理类实现的接口的class类
* 3 invocationHandler的子类,在这个类中的invoke方法中前后加入加强的逻辑
我自己写了一个实例:
该实例模拟spring的AOP机制,即我们只要在配置文件里打开了事务机制,
* 那么调用方法就会开启事务,同样我们在配置文件里关闭了事务机制,那么调用方法就不会开启事务
AOP java
package proxy;
public interface AOP {
public void show(String str);
public String say(String str);
}
AOP java 实现
package proxy;
public class AOPImpl implements AOP{
@Override
public void show(String str) {
System.out.println("show"+str);
}
@Override
public String say(String str) {
return "say"+str;
}
}
AOP handler:
package proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Map;
public class AOPHandler implements InvocationHandler {
private Object object;
private boolean flag;
public AOPHandler(Object object){
this.object=object;
}
public void setFlag(Map<String, String> config){
if(config==null){
flag=false;
}else{
if(config.containsKey("transaction")&& "true".equalsIgnoreCase(config.get("transaction"))){
flag=true;
}else{
flag=false;
}
}
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if(flag){
doBefore();
}
Object result=method.invoke(object, args);
if(flag){
doAfter();
}
return result;
}
public void doBefore(){
System.out.println("Transcation start...");
}
public void doAfter(){
System.out.println("Transcation commit....");
}
}
Client java
package proxy;
import java.lang.reflect.Proxy;
/*
* 该实例模拟spring的AOP机制,即我们只要在配置文件里打开了事务机制,
* 那么调用方法就会开启事务,同样我们在配置文件里关闭了事务机制,那么调用方法就不会开启事务
*/
public class Client {
public static void main(String[] args) throws Exception{
AOPImpl impl=new AOPImpl();
AOPHandler handler=new AOPHandler(impl);
handler.setFlag(JVMCache.getConfig());
System.out.println(JVMCache.getConfig()+"提示");
/*
* 利用Proxy的newProxyInstance的静态方法,就可以动态生成一个代理类
* 这个方法有三个参数
* 1 类加载器,将动态生成的代理类的字节码文件加载到jvm虚拟机中
* 2 被代理类实现的接口的class类
* 3 invocationHandler的子类,在这个类中的invoke方法中前后加入加强的逻辑
*
*/
AOP aop=(AOP)Proxy.newProxyInstance(AOPImpl.class.getClassLoader(),
new Class<?>[] {AOP.class}, handler);
aop.show("我擦擦");
String result=aop.say("杭州G20峰会");
System.out.println(result);
}
}
JVM Cache java
package proxy;
import java.util.Map;
public class JVMCache {
private static Map<String, String> config;
public synchronized static Map<String, String> getConfig() throws Exception{
if(null==config){
config=XMLUtil.parseXml();
}
return config;
}
}
XMLUtil java
package proxy;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class XMLUtil {
public static Map<String, String> parseXml ()throws Exception{
Map<String, String> result=new HashMap<String, String>();
DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
DocumentBuilder db=dbf.newDocumentBuilder();
InputStream in=XMLUtil.class.getClassLoader().getResourceAsStream("config.xml");
Document document=db.parse(in);
Element root=document.getDocumentElement();
NodeList xmlNodes=root.getChildNodes();
for(int i=0;i<=xmlNodes.getLength();i++){
Node config=xmlNodes.item(i);
if(null!=config &&config.getNodeType()==Node.ELEMENT_NODE){
String nodeName=config.getNodeName();
System.out.println(nodeName+"输出节点名称为:");
if("transaction".equals(nodeName)){
String textContent=config.getTextContent();
result.put("transaction", textContent);
System.out.println("你好啊");
}
}
}
return result;
}
}
config.xml java
<?xml version="1.0" encoding="UTF-8"?>
<config>
<transaction>true</transaction>
</config>
运行时结果为:
transaction输出节点名称为:
你好啊
{transaction=true}提示
Transcation start...
show我擦擦
Transcation commit....
Transcation start...
Transcation commit....
say杭州G20峰会
OK ,将配置文件里面的值改为false
运行
事务自动关闭,ok ,到此结束
- java中的动态代理
- java中的动态代理》》》》》
- JAVA 中的 动态代理
- java中的动态代理
- java中的动态代理
- Java中的动态代理
- Java中的动态代理
- JAVA中的动态代理
- java中的动态代理
- java中的动态代理
- java 中的动态代理
- Java中的动态代理
- java中的动态代理
- Java中的动态代理
- java中的动态代理
- java中的动态代理
- java中的动态代理
- Java中的动态代理
- 大一下学期做的一个飞机游戏(JAVA)
- 一个元素绑定多个点击事件
- Oracle 软件及静默安装数据库
- 什么是Java反射
- JSONObject简介
- java 中的动态代理
- Mysql数据库事务在jdbc中的用法
- windows平台下Tuxedo应用simpapp编译失败问题解析
- 事务的概念
- 开博记录
- category使用 objc_setAssociatedObject/objc_getAssociatedObject 实现添加属性
- 大型网站技术架构读书笔记
- AFN 与 ASI 有什么区别
- Spark性能优化第七季之Spark 钨丝计划