IOC,AOP单例模式的实现

首先看看我们要做什么

@Component
public class UserConfig {
	public UserConfig() {
	}
	@Bean
	public VideoModel getVideoModel() {
		return new VideoModel();
	}
	@Bean
	public VideoDao getVideoDao(VideoModel video) {
		return new VideoDao(video);
	}
}

加了Component的类,构造就不是用户来操作了,而是交给本文的工具
加了Bean的方法返回值也会实例化,然后用户要用的时候直接从工厂中拿出来。
缺陷以及硬性要求下面会提及。

1.IOC(控制反转),指在程序设计中,实例不再由程序开发者来创建,而是通过容器(spring)来创建,令控制权由应用代码转移到了外部容器,控制反转。
2.DI依赖注入(组合注入),在使用框架创建对象时,动态的将其所依赖的对象注入bean组件中。举例:ClassA 里有ClassB,因此容器在创建A对象是会把B对象实例化并且注入到A之中。
3.Bean:由容器创建的对象。
4.注解(XML也是可以的,不过太多的Bean会令xml文件显得臃肿,这里使用注解标记bean)

ioc与aop是独立的,ioc完成的主要是bean的创建,bean的注入,aop主要实现在方法前后添加业务。如果需要同时的实现IOC与AOP我们的模型应该封装有原对象与代理对象。

public class MyProxy {
	private Object proxy;
	private Object object;
	//通过递归解决循环依赖注入
	private boolean injection;
	//方法拦截器一一对应
	******* getter and  setter*****
	}

原对象和代理对象的模型好了。接下来我们需要一个工厂来生产模型。根据class或object生成模型,当然如果利用object生成模型,模型中的object自然与参数相同。

//根据传来的class和object生成代理对象模型,并且添加拦截器方法
public class ProxyFactory {
	//重载,获取代理模型对象
	public static MyProxy getMyProxy(Object object) {
		Class<?> klass = object.getClass();
		MyProxy myproxy = new MyProxy();
		Object proxy = MakeCGlProxy(klass,object,myproxy);
		myproxy.setObject(object);
		myproxy.setProxy(proxy);
		return myproxy;
	}
	public static MyProxy getMyProxy(Class<?> klass) {
		Object object=null;
		try {
			object = klass.newInstance();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} 
		return getMyProxy(object);
	}
	
	
	//通过klass和object生成代理对象
	@SuppressWarnings("unchecked")
	private static <T> T MakeCGlProxy(Class<?> klass,Object object,MyProxy myProxy) {
    	Enhancer enhancer = new Enhancer();
    	enhancer.setSuperclass(klass);
    	enhancer.setCallback(new MethodInterceptor() {
			//方法拦截器
			@Override
			public Object intercept(Object obj, Method method, Object[] paramterlist, MethodProxy arg3) throws Throwable {
			    //添加拦截器
				return doInvoke(klass, object,method ,paramterlist,myProxy);
			}
		});
    	return (T) enhancer.create();
    }
    
    private static Object doInvoke(Class<?> klass,Object object,Method method,Object[] paramterlist,MyProxy myProxy) {
    	//TODO 从map中查找出来这个代理需要添加的拦截方法添加在方法调用的前后
    	Object result=null;
    	
    	try {
			result = method.invoke(object, paramterlist);
		} catch (Exception e) {
			e.printStackTrace();
		}
        return result;
    }
}

当然,我们以后的拦截器链就会通过方法添加在doInvoke方法中了,相当于给代理添加了拦截方法。
生成的工具类也有了,下一步自然是生成bean工厂来管理这些MyProxy(第一个类)了,这里我们采取恶汉模式,即在包扫描时期就完成全部bean的建立。

public class ProxyBeanFactory {
	//Bean and ClassName
	private static Map<String, String> beanMap;
	//ClassName and MyProxy
	private static Map<String, MyProxy> proxyMap;
	static {
		beanMap=new HashMap<String,String>();
		proxyMap = new HashMap<String ,MyProxy>();
	}
	public static Map<String, MyProxy> getProxyMap() {
		return proxyMap;
	}
	public static Map<String, String> getbeanMap(){
		return beanMap;
	}
	//根据name和classname生成beanMap,之后调用一个方法把klassname和这个klass对应的myProxy生成proxymap
	public static void addBeanMap(String name, Class<?> klass) throws CantNewInstanceException, InstantiationException, IllegalAccessException {
		if(beanMap.containsKey(name)) {
			System.out.println(name+"已经被添加进bean中,可以直接使用");
			return;
		}
		beanMap.put(name, klass.getName());
		addProxyMap(klass);
	}
	public static void addBeanMap(String name,Object object) throws CantNewInstanceException{
		Class<?> klass = object.getClass();
		if(beanMap.containsKey(name)) {
			System.out.println(name+"已经被添加进bean中,可以直接使用");
			return;
		}
		beanMap.put(name, klass.getName());
		addProxyMap(object);
	}
	public static void addProxyMap(Class<?> klass) throws InstantiationException, IllegalAccessException {
	      Object object = klass.newInstance();
	      addProxyMap(object);
	}
	
	public static void addProxyMap(Object object) {
		Class<?> klass = object.getClass();
		if(proxyMap.containsKey(klass.getName())) {
			System.out.println(klass.getName()+"已经被添加进bean中,可以直接使用");
			return;
		}
		MyProxy myProxy = ProxyFactory.getMyProxy(object);
		proxyMap.put(klass.getName(), myProxy);
	}
	
	public static void createBean(Class<?> klass) throws CantNewInstanceException {
		Object object=null;
		try {
			object = klass.newInstance();
		} catch (InstantiationException | IllegalAccessException e) {
		 throw new CantNewInstanceException("实例化出错");
		}
		addProxyMap(object);
		return;
	}
	//根据注解名获得My
	public static MyProxy getMyProxyByBeanByClassname(String componentname) {
		String classname = beanMap.get(componentname);
		if(classname==null) {
			System.out.println(classname+"没有加入到bean工厂中");
		}
		return getMyProxyByClassname(classname);
	}
	
	//根据类名获取到MyProxy
	public static MyProxy getMyProxyByClassname(String classname) {
		return proxyMap.get(classname);
	}
	//根据注解名获取到类名
	public static String getClassNameByName(String name) {
		return beanMap.get(name);
	}
	public static MyProxy getBeanByAnnotation(String annotationname) {
		return proxyMap.get(beanMap.get(annotationname));
	}

}

就是beanMap和ProxyMap的添加以及获取,beanMap中存放注解名和类名,ProxyMap中存放类名和代理模型。
接下来,我们要通过包扫描生成我们的map了。思路与缺陷如下:
1,带Component注解的类需要包含一个无参构造。(缺陷1,如果带Component的类没有无参构造,崩溃)
2.通过带参数函数的返回值加入bean时要求参数在方法调用前生成bean,否则崩溃,这就对方法的顺序有了一些限定了。
这是包扫描形成map来管理bean的类,说一下思想,首先包扫描,如果这个类带了Component注解,那么使用NewInstance来进行构造,并且加入Bean工厂(就是那上述两个map),接着扫描这个类的方法,带了bean注解无参方法直接调用,把返回值加入bean,有参数的先管理起来

public class SomeParamterMethod {
	private Method method;
	private Object object;
	private String name;
	public SomeParamterMethod(Method method,
			Object object,String name) {
		this.method = method;
		this.object = object;
		this.name = name;
	}

就这样管理就行。等到包扫描完成了,这个带参方法参数的bean都在工厂了,拿出来调用一下然后直接调用方法获取返回值且加入bean。控制反转就得到了体现

public class BeanFactory {
    public static void scanerPackage(String packagename) throws CantNewInstanceException {
    	List<SomeParamterMethod> methodlist = new ArrayList<SomeParamterMethod>();
    	new PackageScanner() {
			@Override
			public void dealClass(Class<?> klass) {
				try {
					
					makeBeanFactory(klass,methodlist);
				} catch (CantNewInstanceException e) {
					e.printStackTrace();
				} catch (InstantiationException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				}
			}
		}.packageScan(packagename);
		//完成了扫描,此时含参函数的参数值应该都已经在Bean工厂之中
		for(SomeParamterMethod spm : methodlist) {
			//带参数的函数获取实例化返回值
			Object result = dealSomeParamterMethod(spm);
			createBean(result, spm.getName());
		}
    }
  

	//检查该类是否有注解
    private static void makeBeanFactory(Class<?> klass,List<SomeParamterMethod> methodlist) throws CantNewInstanceException, InstantiationException, IllegalAccessException {
    	if(!klass.isAnnotationPresent(Component.class)) {
    		return;
    	}
    	// 表明带有注解,加入生成该类的代理对象
        Component annotation = klass.getAnnotation(Component.class);
        String name = annotation.name();
    	createBean(klass, name);
    	 MyProxy myProxy = ProxyBeanFactory.getMyProxyByClassname(klass.getName());
		 Object object = myProxy.getObject();
    	Method[] methods = klass.getMethods();
    		for(int i=0;i<methods.length;i++)
	    	{
	    		Method method=methods[i];
	    		if( !method.isAnnotationPresent(Bean.class)) {
	    			continue;
	    		}
	    		Bean bean = method.getAnnotation(Bean.class);
	    		String methodname = bean.name();
	    		//对方法处理,不带参数的直接调用,把返回值加入bean,带参数的扔到list里头
	    		dealMethod(method,klass,methodname,methodlist,object);
	    	
	    	}
	    	
    	}
  
    private static void dealMethod(Method method,Class<?> klass,String methodname,
    		List<SomeParamterMethod> methodlist,Object object) throws CantNewInstanceException {
    	//无参数的方法
		 if(method.getParameters().length==0) {
			
			 Object InBean = null;
			 try {
				InBean = method.invoke(object);
				createBean(InBean, methodname);
			} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
				e.printStackTrace();
			}
		 }
		 else {
			 //有参函数,加入队列之中
			 methodlist.add(new SomeParamterMethod(method, object, methodname));
		 }
	}

	//此方法用来把对象实例后加入bean
    private static void createBean(Class<?> klass,String name) throws CantNewInstanceException, InstantiationException, IllegalAccessException {
    	if(name.length()>0) {
    		ProxyBeanFactory.addBeanMap(name, klass);
    		}
    	else {
    		ProxyBeanFactory.addProxyMap(klass);
    	}
    }
 	private static void createBean(Object object,String name) throws CantNewInstanceException{
     	if(name.length()>0) {
     		ProxyBeanFactory.addBeanMap(name, object);
     		}
     	else {
     		ProxyBeanFactory.addProxyMap(object);
     	}
     }
    //处理带参数的函数
    private static Object dealSomeParamterMethod(SomeParamterMethod spm) {
		// 这里头的Object是从bean工厂里拿出来的Object
    	Method method = spm.getMethod();
    	Parameter[] parameters = method.getParameters();
    	Object result = null;
    	Object object = spm.getObjcet();
    	Object[] paramterObjects = new Object[parameters.length];
    	for(int i=0;i<parameters.length;i++) {
    		Parameter parameter = parameters[i];
    	MyProxy mp= ProxyBeanFactory.getMyProxyByBeanByClassname(parameter.getType().getName());
    	Object args = mp.getObject();
    	paramterObjects[i] = args;
    	}
    	try {
			result = method.invoke(object, paramterObjects);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}
    
 
    //根据注解名获取bean工厂里头的bean,应该是代理对象,只有代理对象才能完成aop操作,在此时应该完成依赖注入
    @SuppressWarnings("unchecked")
	public static <T> T getBean(Class<?> klass) {
    	MyProxy myproxy= ProxyBeanFactory.getMyProxyByClassname(klass.getName());
    	if(myproxy.isInjection()==false) {
    		//对模型注入
    		inJection(myproxy);
    	}
    	return (T)myproxy.getProxy();
    }
    private static void inJection(MyProxy myproxy) {
    	Object object = myproxy.getObject();
    	Class<?> klass = object.getClass();
    	Field[] fields = klass.getDeclaredFields();
    	for(int i=0;i<fields.length;i++) {
    		Field field = fields[i];
    		if(!field.isAnnotationPresent(Autowired.class)) {
    			continue;
    		}
    		String name = field.getType().getName();
    		MyProxy myp = ProxyBeanFactory.getMyProxyByClassname(name);
    		Object injectObj = myp.getObject();
    		//还没有注入,递归
    		if(myproxy.isInjection()==false) {
    			myproxy.setInjection(true);
    		     inJection(myp);
    		}
    		//这个带注解,表示需要自动装入
    		field.setAccessible(true);
    		try {
				field.set(object, injectObj);
			} catch (IllegalArgumentException | IllegalAccessException e) {
				e.printStackTrace();
			}
    	}	
    }
}

讲一下最后两个函数,这里用来解决依赖注入,所以我们发现,注入的时期是用户第一次从bean中要取出对象的时候(自然是代理对象,不然无法完成aop),对原对象进行注入,取出来的是代理对象,但是要求对原对象注入,为了解决循环依赖注入造成死循环,我们在myproxy中的Injection属性就起到了作用,我们采取递归解决,对带注解的成员进行赋值,用injection来确认这个是否已经完成成员属性的注入,这就解决了死循环问题。
测试
在这里插入图片描述
三个测试类,A中有B,B中有C,C中有A

public class Test {
	public static void main(String[] args) throws CantNewInstanceException {
		BeanFactory.scanerPackage("com.mec.student");
		//IntercepterScanner.intercepterScanner("com.mec.student");
		//拿到了代理对象
		ClassA a = BeanFactory.getBean(ClassA.class);
		System.out.println(a);
		ClassB b = a.getClassb();
		System.out.println(b);
		ClassC c = b.getClassc();
		System.out.println(c);
		ClassA a2 = c.getClassa();
		System.out.println(a2);
		System.out.println(a.hashCode()+" : "+a2.hashCode());
	}
}

我们看一下结果。

在这里插入图片描述
这不是new出来的,是从bean工厂中取出来的,这就说明了我们成功完成了IOC,单例的实现了bean工厂,多例模式在接下来会继续讨论。

AOP:首先让我们看看需要做什么事

@Aspect
public class StudentLogger {
	
	public StudentLogger() {
	}
	
	@Before(klass=ClassA.class, method="getClassb")
	public boolean beforegetClassb(int args1,String args2) {
		System.out.println("置前拦截到参数 : "+args1+"  "+args2);
		return true;
	}
	
	@After(klass=ClassA.class, 
			method="getClassb",
			parameterTypes= { int.class ,String.class })
	public ClassB aftergetClassb(ClassB b) {
		System.out.println("后置拦截倒了对象" + b.getClass());
		return b;
	}
	
	@Before(klass=ClassA.class, method="getClassb")
	public boolean getClassb(int args1,String args2) {
		System.out.println("第二次前置拦截!");
		return true;
	}
	
	@Before(klass=ClassA.class, method="getClassb")
	public boolean beforegetClassb2(int args1,String args2) {
		System.out.println("对DAO的拦截:" + args1);
		return true;
	}
}

我们要做的是:1,让这些加了注解的方法在被拦截方法前后调用,
2,拦截的方法已经写在了注解里面,根据注解信息给类加拦截。

其实思路一样,先包扫描一波,把信息抽象成模型管理,然后再代理那里写个方法,把是对这个对象添加拦截的方法找出来,前置拦截前置调用,后置拦截后置调用。
好了,大体框架出来了,我们细想一下该把信息怎么抽象出来,拦截方法和被拦截方法应该是什么关系, 是我们写一个带注解的拦截方法就能拦截许多被拦截方法?
是一对多,多对一,还是多对多。你是对一个类添加20个拦截的机会多还是对20个类添加一个拦截机会多呢?其实都很多,这要根据具体需求来定了,小编只在这里讲述一下一对一的处理,因为一对多,多对一,多对多对注解的信息要求就需要程序员自己来定了,一对一是最简单的,易于理解。

开始代码吧,首先来个工厂来管理这些拦截方法

public class IntercepterFactory {
	//这个类的什么方法被添加了什么拦截方法,这两个模型在下面讲解
	private static final Map<IntercepterTargetDefination, List<IntercepterMethodDefination>> beforeMap; 
	private static final Map<IntercepterTargetDefination, List<IntercepterMethodDefination>> afterMap; 
	private static final Map<IntercepterTargetDefination, List<IntercepterMethodDefination>> exceptionMap;
	
	static {
		beforeMap = new HashMap<>();
		afterMap = new HashMap<>();
		exceptionMap = new HashMap<>();
	}
	
	protected IntercepterFactory() {
	}
	
	private void addIntercepter(
			Map<IntercepterTargetDefination, List<IntercepterMethodDefination>> map,
			IntercepterTargetDefination interTarget,
			IntercepterMethodDefination intercepter) {
		List<IntercepterMethodDefination> methodList = map.get(interTarget);
		
		if (methodList == null) {
			synchronized (IntercepterFactory.class) {
				if (methodList == null) {
					methodList = new ArrayList<>();
					map.put(interTarget, methodList);
				}
			}
		}
		methodList.add(intercepter);
	}
	
	protected void addBeforeIntercepter(IntercepterTargetDefination interTarget,
			IntercepterMethodDefination intercepter) {
		addIntercepter(beforeMap, interTarget, intercepter);
	}
	
	protected void addAfterIntercepter(IntercepterTargetDefination interTarget,
			IntercepterMethodDefination intercepter) {
		addIntercepter(afterMap, interTarget, intercepter);
	}
	
	protected void addExceptionIntercepter(IntercepterTargetDefination interTarget,
			IntercepterMethodDefination intercepter) {
		addIntercepter(exceptionMap, interTarget, intercepter);
	}
	
	protected List<IntercepterMethodDefination> getBeforeIntercepterList(
			IntercepterTargetDefination interTarget) {
		return beforeMap.get(interTarget);
	}
	
	protected List<IntercepterMethodDefination> getAfterIntercepterList(
			IntercepterTargetDefination interTarget) {
		return afterMap.get(interTarget);
	}
	
	protected List<IntercepterMethodDefination> getExceptionIntercepterList(
			IntercepterTargetDefination interTarget) {
		return exceptionMap.get(interTarget);
	}
	
}

键是确定要拦截的类,值是具体的拦截方法。三个map,分别存储前后置和异常。
这是值,什么类的什么方法要被拦截时的具体方法
public class IntercepterMethodDefination {
private Class<?> klass;
private Method method;
private Object object;

IntercepterMethodDefination() {
}

IntercepterMethodDefination(Class<?> klass, Method method, Object object) {
	this.klass = klass;
	this.method = method;
	this.object = object;
}
********getter and setter****
}

键被拦截的方法

public class IntercepterTargetDefination {
	private Class<?> klass;
	private Method method;
	
	public IntercepterTargetDefination(Class<?> klass, Method method) {
		this.klass = klass;
		this.method = method;
	}
}

模型好了,我们分析一下拦截方法和被拦截方法之间的联系吧。
前置:前置拦截方法返回值应该是boolean类型的,来确定是否要拦截,参数应该和被拦截方法的一样,以便于做一些操作,等于在函数调用前就把参数拿过来做一些处理。在开发中,拦截方法和被拦截方法应该都是用户来编写的。
后置:自然是对被拦截方法的返回值处理一下再返回了。
异常:看用户自己了。
好了知道有什么限制了,包扫描生成工厂

public class IntercepterScanner {
	
	public IntercepterScanner() {
	}
	//通过包扫描扫描出带@after @befor @throwException的方法,加入我们的bean之中
	public static void intercepterScanner(String packageName) {
		new PackageScanner() {
			
			@Override
			public void dealClass(Class<?> klass) {
				if (!klass.isAnnotationPresent(Aspect.class)) {
					return;
				}
				try {
					Object object = klass.newInstance();
					Method[] methods = klass.getDeclaredMethods();
					for (Method method : methods) {
						try {
							//根据不同的方法注解,添加到不同的数据仓库里头。
							if (method.isAnnotationPresent(Before.class)) {
								//前置拦截
								Before before = method.getAnnotation(Before.class);
								dealBeforeInterceptor(klass, object, method, before);
							} else if (method.isAnnotationPresent(After.class)) {
								//后置拦截
								After after = method.getAnnotation(After.class);
								dealAfterInterceptor(klass, object, method, after);
							} else if (method.isAnnotationPresent(ThrowException.class)) {
								//错误拦截
								ThrowException throwException = method.getAnnotation(ThrowException.class);
								dealExceptionInterceptor(klass, object, method, throwException);
							}
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}.packageScan(packageName);
	}
	
	
	private static void dealBeforeInterceptor(Class<?> klass, Object object, 
			Method method, Before before) throws Exception {
		// 前置拦截器方法的返回值必须是boolean
		// 前置拦截器方法的参数必须是Object[],事实是相关方法的实参,就是说前置拦截方法的参数就是被拦截方法的参数
		// 若不满足上述要求,应该抛出异常。
		Class<?> returnType = method.getReturnType();
		if (!returnType.equals(boolean.class)) {
			throw new Exception("前置拦截器("
					+ method + ")返回值类型只能是boolean");
		}
		Class<?> targetKlass = before.klass();
		Method targetMethod = targetKlass.getMethod(before.method(), 
				method.getParameterTypes());
		IntercepterMethodDefination imd = new IntercepterMethodDefination(
				klass, method, object);
		IntercepterTargetDefination itd = new IntercepterTargetDefination(targetKlass, targetMethod);
		IntercepterFactory intercepterFactory = new IntercepterFactory();
		intercepterFactory.addBeforeIntercepter(itd, imd);
	}
	
	private static void dealAfterInterceptor(Class<?> klass, Object object, 
			Method method, After after) throws Exception {
		// 后置拦截器方法的返回值必须是Object
		// 后置拦截器方法的参数必须是Object,事实是相关方法的实参
		// 若不满足上述要求,应该抛出异常。
		Class<?> intercepterReturnType = method.getReturnType();
		Class<?> targetKlass = after.klass();
		
		Method targetMethod = targetKlass.getMethod(after.method(), 
				after.parameterTypes());
		Class<?> targetReturnType = targetMethod.getReturnType();
		
		if (!intercepterReturnType.equals(targetReturnType)) {
			throw new Exception("后置拦截器("
					+ method + ")的返回值类型不是" + targetReturnType);
		}
		
		IntercepterMethodDefination imd = new IntercepterMethodDefination(
				klass, method, object);
		IntercepterTargetDefination itd = new IntercepterTargetDefination(targetKlass, targetMethod);
		IntercepterFactory intercepterFactory = new IntercepterFactory();
		intercepterFactory.addAfterIntercepter(itd, imd);
	}
	
	private static void dealExceptionInterceptor(Class<?> klass, Object object, 
			Method method, ThrowException throwException) throws Exception {
		// 异常拦截器方法的返回值必须是void
		// 异常拦截器方法的参数必须是Throwable,事实是相关方法的实参
		// 若不满足上述要求,应该抛出异常。
		Class<?> returnType = method.getReturnType();
		if (!returnType.equals(void.class)) {
			throw new Exception("异常拦截器("
					+ method + ")返回值类型只能是void");
		}
		Class<?>[] parameterTypes = method.getParameterTypes();
		if (parameterTypes.length != 1 || !parameterTypes[0].equals(Throwable.class)) {
			throw new Exception("异常拦截器("
					+ method + ")形参类型只能是Throwable");
		}
		
		Class<?> targetKlass = throwException.klass();
		Method targetMethod = targetKlass.getMethod(throwException.method(), Throwable.class);
		IntercepterMethodDefination imd = new IntercepterMethodDefination(
				klass, method, object);
		IntercepterTargetDefination itd = new IntercepterTargetDefination(targetKlass, targetMethod);
		IntercepterFactory intercepterFactory = new IntercepterFactory();
		intercepterFactory.addBeforeIntercepter(itd, imd);
	}
}

这里没什么难点,就是把对应的数据封装到各自的对象中,在分类扔在map里就行了。只要弄清楚了拦截方法和被拦截方法的区别,这里就很容易了。

工厂又好了,接下来就是考虑怎么加了,拦截嘛,自然要加在代理生成的时候,代理里的api有刚刚好有method,那就是根据method来找到拦截的方法了。
public class DoIntercepter {

	//这个method是被拦截的方法
	public static boolean doBefore(Class<?> klass, Method method, Object[] args) {
		IntercepterFactory intercepterFactory = new IntercepterFactory();
		//生成键
		IntercepterTargetDefination itd = new IntercepterTargetDefination(klass, method);
		//根据键找到了这个方法的所有拦截方法
		List<IntercepterMethodDefination> intercepterList = 
				intercepterFactory.getBeforeIntercepterList(itd);
		if (intercepterList == null) {
			return true;
		}
		//逐个调用拦截方法
		for (IntercepterMethodDefination imd : intercepterList) {
			Method intercepterMethod = imd.getMethod();
			Object intercepterObject = imd.getObject();
			boolean result = false;
			try {
				//调用加了注释的拦截器方法
				result = (Boolean) intercepterMethod.invoke(intercepterObject, args);
			} catch (Exception e) {
				e.printStackTrace();
			}
			if (result == false) {
				return false;
			}
		}
		
		return true;
	}
	
	public static Object doAfter(Class<?> klass, Method method, Object result) {
		IntercepterFactory intercepterFactory = new IntercepterFactory();
		IntercepterTargetDefination itd = new IntercepterTargetDefination(klass, method);
		List<IntercepterMethodDefination> intercepterList = 
				intercepterFactory.getAfterIntercepterList(itd);
		if (intercepterList == null) {
			return result;
		}
		for (IntercepterMethodDefination imd : intercepterList) {
			Method intercepterMethod = imd.getMethod();
			Object intercepterObject = imd.getObject();
			try {
				result = intercepterMethod.invoke(intercepterObject, result);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
		return result;
	}
	
	public static void doException(Class<?> klass, Method method, Throwable th) {
		IntercepterFactory intercepterFactory = new IntercepterFactory();
		IntercepterTargetDefination itd = new IntercepterTargetDefination(klass, method);
		List<IntercepterMethodDefination> intercepterList = 
				intercepterFactory.getExceptionIntercepterList(itd);
		if (intercepterList == null) {
			return;
		}
		for (IntercepterMethodDefination imd : intercepterList) {
			Method intercepterMethod = imd.getMethod();
			Object intercepterObject = imd.getObject();
			try {
				intercepterMethod.invoke(intercepterObject, th);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
}

上述代码重复性极高,但小编还没有找到合适的解决思路,因为参数不一样,调用不一样,看似差不多,但哪哪都不一样,搞得抽取很难,如果您有好的建议请提出,感谢。

最后一部:扔到代理生成那里去

public class ProxyFactory {
	//重载,获取代理模型对象
	public static MyProxy getMyProxy(Object object) {
		Class<?> klass = object.getClass();
		MyProxy myproxy = new MyProxy();
		Object proxy = MakeCGlProxy(klass,object);
		myproxy.setObject(object);
		myproxy.setProxy(proxy);
		return myproxy;
	}
	public static MyProxy getMyProxy(Class<?> klass) {
		Object object=null;
		try {
			object = klass.newInstance();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} 
		return getMyProxy(object);
	}


//通过klass和object生成代理对象
@SuppressWarnings("unchecked")
private static <T> T MakeCGlProxy(Class<?> klass,Object object) {
	Enhancer enhancer = new Enhancer();
	enhancer.setSuperclass(klass);
	MethodInterceptor methodInterceptor =new MethodInterceptor() {
		//方法拦截器
		@Override
		public Object intercept(Object obj, Method method, Object[] paramterlist, MethodProxy arg3) throws Throwable {
		    //添加拦截器
			return doInvoke(klass, object,method ,paramterlist);
		}
	};
	enhancer.setCallback(methodInterceptor);
	return (T) enhancer.create();
}

private static Object doInvoke(Class<?> klass,Object object,Method method,Object[] paramterlist) {
	//TODO 从map中查找出来这个代理需要添加的拦截方法添加在方法调用的前后
	Object result=null;
	if (DoIntercepter.doBefore(klass, method, paramterlist) == false) {
		return null;
	}
	try {
		result = method.invoke(object, paramterlist);
		// 后置拦截
		DoIntercepter.doAfter(klass, method, result);
	} catch (Throwable e) {
		// 异常拦截
		e.printStackTrace();
		DoIntercepter.doException(klass, method, e);
	}
    return result;
}
}

最后一波测试
public static void main(String[] args) throws CantNewInstanceException {
BeanFactory.scanerPackage(“com.mec.student”);
IntercepterScanner.intercepterScanner(“com.mec.student”);
//拿到了代理对象
ClassA a = BeanFactory.getBean(ClassA.class);
ClassB b = a.getClassb(2,“46546”);
}
在这里插入图片描述
没问题呀,完成了aop与ioc了。
当然这里还有细节可以增强,比如多例模式的,这些东西不难,但实现起来过于庞杂和扣细节,我们只要知道了实现的原理,细节可以通过后天的慢慢思索来进行修改和操作,本文结束。
指导老师:微易码

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值