java反射与代理模式

反射

(1) 在运行中分析类的能力
(2) 在运行中查看和操作对象
-基于反射自由创建对象
-反射构建出现在无法直接访问的类
-set或者get到无法访问的成员变量
-调用不可访问的方法
-实现通用的数组操作代码
-类似于函数指针的功能
(3) 代码示例
Object obj6 = Class.forName(“全限定类名”).newInstance();
Method m = Class.forName((“全限定类名”).getMethod(“当前类中的方法”);
m.invoke(params); //执行次方法
//获取当前类中的所有方法
Method[] methods = clazz.getDeclaredMethods();
(4) class.getField 获取当前类中的所有成员变量包括继承来的
class.getDeclareFiled 获取当前类中所有成员变量(不包括继承来的)
class.getMethod()同class.getField一样
class.getDeclareMethod同class.getDeclareFiled一样
(5) 在这里插入图片描述(6) 临时使一个类中private修饰的变量或者方法变为public的方式
m.setAccessible(true);
f.setAccessible(true);

java代理

(1)java代理分为静态代理和动态代理
(2)静态代理
代理对象持有目标对象的句柄
所有调用目标对象的方法,都调用代理对象的一个方法
对每一个方法都需要静态编码
(3) 静态代理实现较为简单,但是需要在代理对象中对每一个目标对象的方法进行重写,所以如果方法多了之后,代码量就会变的很大.
(4) 代码示例

//目标对象接口
public interface Subject{
    public void request();
}

//目标对象
class SubjectImpl implements Subject{
  public void request(){
      System.out.println("I am dealing the request.");
  }
}
//代理对象
class StaticProxy implements Subject{
	//实际目标对象
    private Subject subject;
    
    public StaticProxy(Subject subject){
        this.subject = subject;
    }
    
    public void request(){
        System.out.println("PreProcess");
        subject.request();
        System.out.println("PostProcess");
    }
}
//静态代理模式
public class StaticProxyDemo {
    public static void main(String args[]){
    	//创建实际对象
        SubjectImpl subject = new SubjectImpl();
        
        //把实际对象封装到代理对象中
        StaticProxy p = new StaticProxy(subject);
        p.request();
    }
}

动态代理

1 动态代理
-对目标对象的方法每次被调用,进行动态拦截 在这里插入图片描述在这里插入图片描述2 动态代理中最重要的是代理处理器
1 持有目标对象的句柄
2 实现invacationHandler接口
-实现invoke方法
-所有的代理对象方法调用,都会转发到invoke方法中来
-invoke的形参method,是指代理对象方法的调用
-在invoke内部,可以根据method指定代理对象方法的调用。
3 代理对象
-根据给定的接口,由Proxy类自动生成对象
-类型com.sun.proxy继承自java.lang.reflect.Proxy
-通常和目标对象实现同样的接口
-实现多个接口,接口的排序非常重要
4 代码示例

//目标对象接口
public interface Subject{
    public void request();
}
//目标对象
class SubjectImpl implements Subject{
  public void request(){
      System.out.println("I am dealing the request.");
  }
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * 代理类的调用处理器
 */
class ProxyHandler implements InvocationHandler{
    private Subject subject;
    public ProxyHandler(Subject subject){
        this.subject = subject;
    }
    
    //此函数在代理对象调用任何一个方法时都会被调用。
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
    	System.out.println(proxy.getClass().getName());
    	//定义预处理的工作,当然你也可以根据 method 的不同进行不同的预处理工作
        System.out.println("====before====");
        Object result = method.invoke(subject, args);
        System.out.println("====after====");
        return result;
    }
}
import java.lang.reflect.Proxy;
//动态代理模式
public class DynamicProxyDemo {
    public static void main(String[] args) {
    	//1.创建目标对象
    	SubjectImpl realSubject = new SubjectImpl();    
    	
    	//2.创建调用处理器对象
    	ProxyHandler handler = new ProxyHandler(realSubject); 
    	
    	//3.动态生成代理对象
        Subject proxySubject = 
        		(Subject)Proxy.newProxyInstance
        		  (SubjectImpl.class.getClassLoader(),
                   SubjectImpl.class.getInterfaces(), handler); 
        //proxySubject真实类型com.sun.proxy.$Proxy0
        //proxySubject继承Proxy类,实现Subject接口
        //newProxyInstance的第二个参数,就是指定代理对象的接口
        
        //4.客户端通过代理对象调用方法
        //本次调用将自动被代理处理器的invoke方法接收
        proxySubject.request();    
        
        System.out.println(proxySubject.getClass().getName());
        System.out.println(proxySubject.getClass().getSuperclass().getName());
    }
}

简略代理模式

package ceshi;

import java.util.Map;
/*
*  代理接口
* */
public interface IServiceProxy<T,K> {

    void  doServer(T s,K v);
}
package ceshi;

import java.util.Map;

/**
 * @Description 代理实现类1
 * @Auther hanlin
 * @Date 2019/12/22 13:53
 * @Version 1.0
 **/
public class DoserverTest1 implements IServiceProxy {

    @Override
    public void doServer(Object s, Object v) {
        System.out.println("这是测试1"+s+v);
    }
}
package ceshi;
/**
 * @Description 代理实现类2
 * @Auther hanlin
 * @Date 2019/12/22 13:58
 * @Version 1.0
 **/
public class DoserverTest2 implements IServiceProxy {
    @Override
    public void doServer(Object s, Object v) {
        System.out.println("这是测试2"+s+v);
    }
}
package ceshi;
/**
 * @Description 代理对象类,用来操作公共部分,如公共报文头的操作,事务回滚,冲正,记录日志信息等
 * @Auther hanlin
 * @Date 2019/12/22 13:59
 * @Version 1.0
 **/
public class Proxy {
    private  IServiceProxy target = null;

    public Proxy(IServiceProxy target){
        this.target = target;
    }
     
    //执行真正业务逻辑处理的方法
    public void invok(){
       target.doServer(null,null);
    }
}

结论:总而言之无论你先干什么总回先进入这个代理,执行完这个代理类的逻辑,然后在去执行你真正的业务逻辑,所以你写的每一个业务类都要实现我的doserver方法,然后在这个doserver方法中进行你全部的业务逻辑处理.

AOP编程

1 面向切面编程和面向对象编程的区别
面向对象:将需求功能划分为不同的独立的封装良好的类,并让他们通过继承和多态实现相同或者不同的行为
面向切面:将通用功能需求从更多类中分离出来,使得很多类共享一个行为,一旦发生变化,不必修改很多类,而只需要修改这个行为就可以了.
2 Aop的主要内容
Aspect:配置文件,包括一些pointcut和相应的advice
Joint point: 在程序中明确定义的点,如方法调用和类成员的访问
Pointcut :一组joint point,可以通过逻辑关系/通配符/正则等组合起来/定义了相对的advice要发生的地方。
Advice:定义了在pointcut处要发生的动作,通过before/after/around/来关联
weaving:advice代码在joint pomt 的关联方式
3 代码示例

<--在aop配置文件中配置执行某个方法之前要干什么aop.xml-->
<aops>
   	<aop>
   		<method>washHand</method>
   		<type>before</type>
   		<method>eat</method>
   	</aop>
</aops>

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.StringReader;

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;
import org.xml.sax.InputSource;
//读取xml配置文件
public class XmlReader {

	
	public static void readXml(String filePath){
		String xml = load(filePath);
		try{
			DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
			Document document;
			DocumentBuilder dbBuilder = dbFactory.newDocumentBuilder();
			StringReader sr = new StringReader(xml);		  
			InputSource is = new InputSource(sr);
			document = dbBuilder.parse(is);
			Element root = document.getDocumentElement();
			findMethod(root.getChildNodes());
		}
		catch(Exception e){
			e.printStackTrace();
		}
	}
	
	public static void findMethod(NodeList elementList){
		for (int i = 0; i < elementList.getLength(); i++) {
			Node elementNode = elementList.item(i);
			//System.out.println("allnode: "+elementNode.getNodeName());
			if (elementNode.getNodeType() == Node.ELEMENT_NODE) {
				Element element = (Element) elementNode;
				String name = element.getNodeName();
				if(name.equalsIgnoreCase("aop")){
					readMethod(element.getChildNodes());
				}
				else{
					findMethod(element.getChildNodes());
				}
			}
		}
	}
	
	private static void readMethod(NodeList elementList){
		String methodName = "";
		for (int i = 0; i < elementList.getLength(); i++) {
			Node elementNode = elementList.item(i);
			if (elementNode.getNodeType() == Node.ELEMENT_NODE) {
				Element element = (Element) elementNode;
				String name = element.getNodeName();
				if(name.equals("method")){
					if(methodName==null||methodName.length()==0)methodName = element.getFirstChild().getTextContent();
				}
				else if(name.equals("type")){
					String type = element.getFirstChild().getTextContent();
					if(type.equals("after")){
						ProxyHandler.afterMethod = methodName;
					}
					else{
						ProxyHandler.beforeMethod = methodName;
					}
					
				}
			}
		}
	}
	
	private static String load(String path){
		try{
			File file = new File(path);
	        FileReader reader = new FileReader(file);
	        BufferedReader bReader = new BufferedReader(reader);
	        StringBuilder sb = new StringBuilder();
	        String s = "";
	        while ((s =bReader.readLine()) != null) {
	            sb.append(s + "\n");
	            //System.out.println(s);
	        }
	        bReader.close();
	        return sb.toString();
		}
		catch(Exception e){
			e.printStackTrace();
		}
		return null;
	}

}

import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
//监听配置文件是否发生了变化
public class ResourceListener {

	private static ExecutorService fixedThreadPool=Executors.newCachedThreadPool();
    private WatchService ws;
    private String listenerPath;
    private ResourceListener(String path){
        try
        {
            ws=FileSystems.getDefault().newWatchService();
            this.listenerPath=path;
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
    private void start(){
        fixedThreadPool.execute(new Listener(ws, listenerPath));
    }
    
    public static void addListener(String path){
    	try{
    		ResourceListener resourceListener=new ResourceListener(path);
            Path p=Paths.get(path);
            p.register(resourceListener.ws, StandardWatchEventKinds.ENTRY_MODIFY,StandardWatchEventKinds.ENTRY_DELETE,
                StandardWatchEventKinds.ENTRY_CREATE);
            resourceListener.start();
    	}
    	catch (Exception e){
    		e.printStackTrace();
    	}
    	
    }
    
    
    class Listener implements Runnable{

    	WatchService ws;
    	String listenerPath;
    	
    	Listener(WatchService ws,String listenerPath){
    		this.ws = ws;
    		this.listenerPath = listenerPath;
    	}
    	
		@Override
		public void run() {
			try {  
                while(true){  
                    WatchKey watchKey = ws.take();  
                    List<WatchEvent<?>> watchEvents = watchKey.pollEvents();  
                    for(WatchEvent<?> event : watchEvents){  
                    	String context = event.context().toString();//对象
                    	String kind = event.kind().toString();//变更类型
                    	if(context.equals("aops.xml")){
                    		if(kind.equals("ENTRY_MODIFY")){
                    			XmlReader.readXml(listenerPath+"/"+event.context());
                    		}
                    	}
                    }  
                    watchKey.reset();  
                }  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
                try {
                    ws.close();
                } catch (Exception e1) {
                }
            }
		}
    	
    }
}

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Arrays;

//代理类
public class ProxyHandler implements InvocationHandler {
	
	static String beforeMethod = "";
	static String afterMethod = "";
	
	private Person receiverObject;
	
	public ProxyHandler(Person object){
		this.receiverObject = object;
	}
	
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		//处理before方法
		if(beforeMethod!=null&&beforeMethod.length()>0){
			ClassLoader cl = ProxyHandler.class.getClassLoader();
			Class<?> c = cl.loadClass(receiverObject.getClass().getName());
			Method m=c.getMethod(beforeMethod);
			Object obj = c.newInstance();
			m.invoke(obj);
		}
		
		//处理目标方法
		Object result = method.invoke(receiverObject, args);
		
		//处理after方法
		if(afterMethod!=null&&afterMethod.length()>0){
			method.invoke(receiverObject, args);
			ClassLoader cl = ProxyHandler.class.getClassLoader();
			Class<?> c = cl.loadClass(receiverObject.getClass().getName());
			Method m=c.getMethod(afterMethod);
			Object obj = c.newInstance();
			m.invoke(obj);
		}
		return result;
	}

}
//接口
public interface Person {

	void eat();
	void washHand();
	void bath();
}
//接口实现类
public class PersonImpl implements Person {

	public void eat() {
		System.out.println("I am eating");
	}

	public void washHand() {
		System.out.println("I am washing hands");

	}

	public void bath() {
		System.out.println("I am bathing");

	}

}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;


//测试类
public class Main {

	
	public static void initXml(){
		XmlReader.readXml("aops.xml");
		ResourceListener.addListener("E:/java/source/PMOOC04-03/");
	}	
	
	public static void main(String[] args) throws Exception{
		Main.initXml();		
		
		Person action = new PersonImpl();
		ProxyHandler mh = new ProxyHandler(action);
		ClassLoader cl = Main.class.getClassLoader();
		Class<?> proxyClass = Proxy.getProxyClass(cl, new Class<?>[]{Person.class});
        Person proxy = (Person) proxyClass.getConstructor(new Class[]{InvocationHandler.class}).
                newInstance(new Object[]{mh});
        
        while(true)
        {
			proxy.eat();
			try{
				Thread.sleep(3000);
			}
			catch(Exception e){
				e.printStackTrace();
			}
		}
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值