黑马程序员——高新技术—AOP面向方面编程

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

空中网面试题

       本题要求键相同的两个对象间隔1秒进行输出,键不同的对象同时输出,另外即使键在字面上相同,即用equals进行内容比较一致,但由于每个键与空字符串进行相连,形

成了新的字符串,故即使是字符串常量,但也是两个不同的对象。

       故第一步是能不能想到用键作为同步锁,第二步是用线程同步的集合进行键值的存储,第三步是当集合中存在equals相等的键时,要获取同一把锁。

       另外一点值得注意的是ArrayList在进行迭代操作时,不能引用集合对象来操作集合中的元素,如在迭代时进行元素的增删。这是因为通过参看源代码,迭代器的hasNext方

法在返回值前会比较spectedCount与subCount的值(是在调用迭代器之前由集合增删方法所累加起来的值先赋给subCount,再赋给spectedCount,若在迭代器中再调用集合

中的增删方法,则累加的只有subCount,当两值不等时,hasNext方法会抛出异常)。

package cn.itcast;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArrayList;

public class CollectionElementsAsLock extends Thread{
	private String key=null;
	private String value=null;
	private PrintKeyValue instance=null;
	public CollectionElementsAsLock(String key,String key2,String value) {
		// TODO Auto-generated constructor stub
		instance=PrintKeyValue.getInstance();
		this.key=key+key2;
		this.value=value;
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println("begin:"+System.currentTimeMillis()/1000);
		new CollectionElementsAsLock("1", "", "张三").start();
		new CollectionElementsAsLock("1", "", "李四").start();
		new CollectionElementsAsLock("2", "", "王五").start();
		new CollectionElementsAsLock("3", "", "赵六").start();
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		instance.print(key, value);
	}
}
class PrintKeyValue{
	private PrintKeyValue(){};
	private static PrintKeyValue instance=new PrintKeyValue();
	public static PrintKeyValue getInstance(){
		return instance;
	}
//	private Collection keys=new ArrayList();
	private CopyOnWriteArrayList keys=new CopyOnWriteArrayList();
	public void print(String key,String value){
		String realKey=key;
		if(!keys.contains(key)){
			keys.add(key);
		}else{
			for(Iterator it=keys.iterator();it.hasNext();){
				try {
					Thread.sleep(20);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				String tmp=it.next();
				if(tmp.equals(realKey)){
					realKey=tmp;
				}
			}
		}
		synchronized (realKey) {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(key+":"+value+":"+System.currentTimeMillis()/1000);
		}
	}
}

AOP面向方面编程

        AOP,面向方面编程,即为各个API类设置代理,在代理类中往往设置一个target(目标字段,即API类)和advice(Advice接口,用于功能扩展)两个字段,目标类可为一

般API类,通过实现Advice接口为API类附加其他功能,以代理对象进行返回。代理对象除了具有原API对象的方法之外,还附加了Advice实现类中的部分或全部功能,如性能测

试等。

       代理的出现,可以按需要进行功能扩展,产生大量具备原目标对象功能的加强代理对象。

       本例实现一个Bean工厂,可通过更改配置文件参数产生普通Bean对象和代理对象:

       首先定义规则:


package cn.itcast;

public interface Advice {
	void beforeMethod();
	void afterMethod();
}

       通过实现规则扩展功能:


package cn.itcast;

public class MyAdvice implements Advice {
	long startTime=0;
	@Override
	public void beforeMethod() {
		// TODO Auto-generated method stub
		startTime=System.currentTimeMillis();
	}

	@Override
	public void afterMethod() {
		// TODO Auto-generated method stub
		long endTime=System.currentTimeMillis();
		System.out.println(endTime-startTime);
	}

}

       定义好了扩展功能后,就可以设置代理类:


package cn.itcast;

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

public class ProxyFactoryBean {
	private Object target;
	private Advice advice;
	public Object getTarget() {
		return target;
	}
	public void setTarget(Object target) {
		this.target = target;
	}
	public Advice getAdvice() {
		return advice;
	}
	public void setAdvice(Advice advice) {
		this.advice = advice;
	}
	public Object getProxy(){
		
		return Proxy.newProxyInstance(target.getClass().getClassLoader(),
				target.getClass().getInterfaces(),
				new InvocationHandler() {
			@Override
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				// TODO Auto-generated method stub
				advice.beforeMethod();
				Object retVal=method.invoke(target, args);
				advice.afterMethod();
				return retVal;
			}
		});
	}
}


       Bean工厂:通过InputStream读取配置文件产生普通Bean或代理对象:


package cn.itcast;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class BeanFactory {
	private InputStream ips;
	private Properties props=null;
	public BeanFactory(InputStream ips) {
		super();
		this.ips = ips;
		props=new Properties();
		try {
			props.load(ips);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	public Object getBean(String key){
		Object obj=null;
		try {
			obj=Class.forName(props.getProperty(key)).newInstance();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		if(obj instanceof ProxyFactoryBean){
			ProxyFactoryBean pfb=(ProxyFactoryBean)obj;
			
			Object retVal=null;
			try {
				pfb.setAdvice((Advice)Class.forName(props.getProperty(key+".advice")).newInstance());
				pfb.setTarget(Class.forName(props.getProperty(key+".target")).newInstance());
				retVal=pfb.getProxy();
				
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			return retVal;
		}
		return obj;
	}
}


       config.properties  配置文件如下:


#***=java.util.ArrayList
***=cn.itcast.ProxyFactoryBean
***.target=java.util.HashSet
***.advice=cn.itcast.MyAdvice


   主函数进行测试:


package cn.itcast;

import java.util.Collection;

public class AOPFrameworkTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		BeanFactory beanFactory=new BeanFactory(AOPFrameworkTest.class.getResourceAsStream("config.properties"));
		Object bean=beanFactory.getBean("***");
		System.out.println(bean.getClass().getName());
		Collection collction=(Collection)bean;
		collction.add("a");
		collction.add("b");
		collction.add("c");
		collction.add("b");
		System.out.println(collction.size());
	}

}




















你可能感兴趣的:(黑马程序员——高新技术—AOP面向方面编程)