【java】Spring AOP IOC 初探及实现

最近学习了AOP和IOC,了解并自己实现了Spring中的AOP和IOC

什么是AOP?

       AOP即面向切面编程,能够让我们在不影响原有功能的情况下,对程序进行横向扩展,面向切面?横向扩展?第一次接触这两个词的时候我也是一脸懵逼。

       说说我的理解:如果现有某个类的某个方法是已经封装好的,现在我们需要在执行这个方法的时候加点自己的东西,对原方法的执行进行干预。当然要求是不能破坏原类。这时需要AOP思想,把这个方法,即切点扩展成一个面来进行操作。(生成该类的代理,对代理进行操作)

        例如:给这个方法加日志,执行方法前进行拦截等。

        在上一篇博客中有讲到并手写实现,这里就不多赘述了。>>传送门<<

        今天的目的就是结合AOP IOC


什么是IOC  DI?

       说的高大上就是“依赖注入”“控制反转”。假如现在A类中调用B类的方法,即A依赖B。传统做法:先new一个B,再调用方法。这是需要我们人为主动的去实现,而IOC的作用就是当我们调用需要B的A方法的时候,自动帮我们new出一个B,并将其注入A。

       所以说这时候的对象已经的控制权在IOC容器,而不是靠我们程序员主动控制。

看到过一个有趣的例子:

       我们可以把IOC当做一个婚介所。我现在要找女朋友,我只需要将我的要求告诉IOC这个婚介所,由婚介所在他管理的一堆资料中帮我找到符合我标准的对象,整个过程不需要我们控制,我们只需要和她谈恋爱就好!当然,找不到,婚介所就会通知我们(抛出异常)

       同样,如果我们把主动控制当做自己去炒一盘土豆丝:我们要先准备土豆并切成丝,再热油,再把干辣椒花椒炒香,接着下土豆丝,各种调料,出锅,开吃!而,IOC就相当于饭店,你只需要说:“老板!来盘土豆丝!”(当然前提是我告诉老板我要吃的土豆丝该怎么做)就可以了!


自己的实现思路:

       通过包扫描扫描出带有我注解的方法利用反射机制生成其代理并“存储”之。待我要求的对象再将其依赖的对象注入。在实现的过程中遇到了许许多多的问题。例如:如何处理循环依赖?解决扫描到带参方法时参数还没被扫描到的问题?

话不多说,上图!

比起前一篇,这次在实现的时候自己有了一些变动:这次咱们不用手工来累死累活来的手动添加***了,咱们来动态加入***!

 InterceptorScanner用来包扫描动态添加***,设置Map

FyProxy将代理对象和原对象联系起来 (嘿嘿,这里的是否已经注入是来解决循环依赖问题的)

ProxyFactory产生代理(CGLIB或JDK方式)

ProxyBeanFactory联系类名和fyProxy

BeanFactory包扫描,根据注解自动添加proxyBeanFactory中的Map 

这是***模块,InterceptorFactory中存放了 3个Map,图很清楚的反映了每一个目标方法,都有以一个***链。


好了,现在我也不知道要说啥了,咱看代码说话吧:

FyProxy

	private Object proxy;          // 代理对象
	private Object object;         // 原对象   
	private boolean injection;     // 是否已经注入
	public FyProxy() {               // 构造方法
	    injection = false;           // 没有注入
	}

 get和set方法就不说了

    // 这是代理对象执行方法时会调用的前置***
    // 根据传递过来的类和方法从InterceptorFactory中找到前置***链
    // 遍历***链,实现方法,返回result
    public boolean doBefore(Class<?> klass, Method method, Object[] args) {
		List<InterceptorMethodDefination> list = 
				InterceptorFactory.getBeforeInterceptorList(new InterceptorTargetDefination(klass, method));
		if (list == null) {
			return true;
		}
		for (InterceptorMethodDefination interceptor : list) {
		    Method interceptorMethod = interceptor.getMethod();
		    Object interceptorObject = interceptor.getObject();
		    boolean result = false;
			
		    try {
				result = (Boolean) interceptorMethod.invoke(interceptorObject,args);
			} catch (Exception e) {
				e.printStackTrace();
			}
		    if (result == false) {
		    	return false;
		    }
		}
		return true;
	}

另外该类中还包含doAfter和doException,思路同上,只有传参有稍许不同,也就不多说了。

既然涉及到了InterceptorMethodDefination(***方法) 和 InterceptorTargetDefination(被拦截的目标), 那就先说说他俩吧。

InterceptorTargetDefination(被拦截的目标)

	private Class<?> klass;
	private Method method;

	public InterceptorTargetDefination(Class<?> klass, Method method) {
		super();
		this.klass = klass;
		this.method = method;
	}

        // 我们要拦截,当然只需知道我们拦截的是哪个类的哪个方法就行了

        // 当然下面还有equals方法

InterceptorMethodDefination(***方法)

	private Class<?> klass;
	private Method method;
	private Object object;
    
        // 身为***:我们当然要执行,通过反射机制,所以object必不可少

        // 构造方法
        // 。。。
        // get和set方法

InterceptorFactory

联系被拦截的目标和***链

	private static final Map<InterceptorTargetDefination, List<InterceptorMethodDefination>> beforeMap;
	private static final Map<InterceptorTargetDefination, List<InterceptorMethodDefination>> afterMap;
	private static final Map<InterceptorTargetDefination, List<InterceptorMethodDefination>> exceptionMap;
	
	static {
		beforeMap = new HashMap<>();
		afterMap = new HashMap<>();
		exceptionMap = new HashMap<>();
	}
	public static void addBeforeInterceptor(InterceptorTargetDefination target, 
			InterceptorMethodDefination interceptor) {
		addInterceptor(beforeMap, target, interceptor);
	}

	private static void addInterceptor(Map<InterceptorTargetDefination, List<InterceptorMethodDefination>> map,
			InterceptorTargetDefination target,
			InterceptorMethodDefination interceptor) {
		List<InterceptorMethodDefination> interceptorList = map.get(target);
		
		if (interceptorList == null) {
			synchronized (InterceptorFactory.class) {
				if (interceptorList == null) {
					interceptorList = new ArrayList<>();
					map.put(target, interceptorList);
				}
			}
		}
		interceptorList.add(interceptor);
	}

        // 这是添加***的方法:这里我给出添加前置***的方法,后置和异常同理
        // 通过被拦截目标从Map中获得其***链,给***链添加***

        // 注意!这里为了安全添加了锁,来保证每个目标的***链只有一个

另外,提供了get***链的方法,以前置***为例

	public static List<InterceptorMethodDefination> getBeforeInterceptorList(
			InterceptorTargetDefination target) {
		return beforeMap.get(target);
	}

Proxyfactory

提供两种方式构建代理     设置FyProxy

	private FyProxy fyProxy;

	public Proxyfactory() {
	}
	
	public FyProxy getFyProxy() {
		return fyProxy;
	}
	

CGLIB方式

	public <T> T getCglibProxy(Class<?> klass, Object object) {
		fyProxy = new FyProxy();
		T proxy = cglibProxy(klass, object);
		fyProxy.setProxy(proxy);
		fyProxy.setObject(object);
		return proxy;
	}
	
	@SuppressWarnings("unchecked")
	private <T> T cglibProxy(Class<?> klass, Object object) {
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(klass);
		enhancer.setCallback(new MethodInterceptor() {	
			@Override
			public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy)
					throws Throwable {
				return doInvoker(klass, object, method, args);
			}
		});
		return (T) enhancer.create();
	}

JDK方式

	public <T> T getJdkProxy(Class<?> klass, Object object) {
		fyProxy = new FyProxy();
		T proxy = jdkProxy(klass, object);
		fyProxy.setProxy(proxy);
		fyProxy.setObject(object);
		return proxy;
	}
	
	@SuppressWarnings("unchecked")
	private <T> T jdkProxy(Class<?> klass, Object object) {
		ClassLoader classLoader = klass.getClassLoader();
		Class<?>[] interfaces = klass.getInterfaces();
		
		return (T) Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler() {			
			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				return doInvoker(klass, object, method, args);
			}
		});
	}

代理对象中的内部方法

	@SuppressWarnings("unchecked")
	private <T> T doInvoker(Class<?> klass, Object object, Method method, Object[] args) throws Throwable {
		Object result = null;
		if (fyProxy.doBefore(klass, method, args)) {
			try {
				result = method.invoke(object, args);
				fyProxy.doAfter(klass, method, result);
			} catch (Throwable th) {
				fyProxy.doException(klass, method, th);
			}
		}
		return (T) result;
	}

        // 看,在这里我用到了FyProxy中的doBefore等方法
        // 可以看出代理对象执行真正原对象方法的时候用的object还是原对象自己
        // 代理就是 穿了一层“衣服”而已

ProxyBeanFactory

将类名与FyProxy对应形成Map

	private static final Map<String, FyProxy> beanMap;
	private static final Map<String, String> beanNameMap;
	
	static {
		beanMap = new HashMap<>();
		beanNameMap = new HashMap<>();
	}

        // beanNameMap是类名和注解自定义名字的对应(因为考虑到使用者会在注解中给类名别的“称谓”)
	public <T> T creatCglibProxy(Class<?> klass) throws Exception {
		return cglibProxy(klass, klass.newInstance());
	}
	
	public <T> T creatCglibProxy(Object object) {
		return cglibProxy(object.getClass(), object);
	}
	
        // 以CGLIB方式为例:
        // 这里的目的是最上层创建代理并将其加入Map中
        // 若该类已经存在代理,即fyProxy对象
        // 则直接返回该对象

	@SuppressWarnings("unchecked")
	private <T> T cglibProxy(Class<?> klass, Object object) {
		String className = klass.getName();
		FyProxy fyProxy = beanMap.get(className);
		if (fyProxy != null) {
			return (T) fyProxy.getProxy();
		}
		Proxyfactory proxyfactory = new Proxyfactory();
		T proxy = proxyfactory.getCglibProxy(klass, object);
		beanMap.put(className, proxyfactory.getFyProxy());
		return proxy;
	}
	public void addBeanName(String className, String beanName) throws BeanNameAlreadyExistException {
		String orgClassName = beanNameMap.get(className);
		if (orgClassName != null) {
			throw new BeanNameAlreadyExistException("Bean名称(" + beanName + ")重复!");
		}
		beanNameMap.put(className, beanName);
	}

        // 这个是增加类名和用户注解中自定义类名的对应关系

这个类中还有,根据类或类名getFyproxy的方法,直接从map里面拿,代码也就不贴了。

下面在开始最核心的包扫描和依赖注入的那层之前,一定要先介绍一下我的注解

注解:

***的注解

// 包含***的类

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Aspect {
}

// 前置***方法
// 参数需给出,该***方法是作用于哪个类的哪个方法的
method不填为*号表示 :会给该类的所有方法增加该***

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Before {
	Class<?> klass();
	String method() default "*";
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface After {
	Class<?> klass();
	String method() default "*";
	Class<?>[] parameterTypes();
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ThrowException {
	Class<?> klass();
	String method() default "*";
}

注入的注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Component {
	String name() default "";
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Bean {
	String name() default "";
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Autowired {
	String name() default "";
}

BeanFactory 

扫描出所有bean创建其代理(FyProxy)并加到ProxyBeanFactory中的Map中

包扫描代码在我前几篇博客中发过 >>传送门<<

    // 给定包路径,扫描此包
    public static void scanPackage(String packageName) throws Exception {
		ProxyBeanFactory proxyBeanFactory = new ProxyBeanFactory();

                // 该list的作用?别急,看下面
		List<BeanMethodDefination> methodList = new ArrayList<>();
		
		new PackageScanner() {	
                        // 这里是个内部类,看过我包扫描代码的人应该了解
                        // 这里在循环中
			@Override
			public void dealClass(Class<?> klass) {

                                // 扫描出带有Component的类
				if (!klass.isAnnotationPresent(Component.class)) {
					return;
				}				
				Component component = klass.getAnnotation(Component.class);
				String name = component.name();
				
				try {
                                        // 创建该类的代理
					proxyBeanFactory.creatCglibProxy(klass);
                        
					creatBean(null, klass, name, proxyBeanFactory);

                                        // 执行该类中所有带有Bean注解的方法
                                        // 并执行
                                        // 执行时肯定要原类的对象
                                        // 这就是我在FyProxy中存原类对象的原因
					FyProxy fyProxy = proxyBeanFactory.getFyProxy(klass);
					Object object = fyProxy.getObject();
					
					Method[] methods = klass.getDeclaredMethods();
					for (Method method : methods) {
						if (!method.isAnnotationPresent(Bean.class)) {
							continue;
						}
                                                // 执行方法
						invokeBeanMethod(object, method, proxyBeanFactory, methodList);
					}
				} catch (Exception e) {
					e.printStackTrace();
				}				
			}
		}.packageScanner(packageName);
		

                // 在所有类扫描完毕后
                // 这里遍历了那个list
                // 然后执行list中的method
                // 这个list里面其实是带有参数的方法
                // 为了解决带参方法参数需要对象而该对象所属类没被扫描到的问题
		for (BeanMethodDefination beanMethod : methodList) {
			Class<?> returnType = beanMethod.getReturnType();
			Parameter[] paras = beanMethod.getParameters();
			Object object = beanMethod.getObject();
			String beanName = beanMethod.getBeanName();
			Method method = beanMethod.getMethod();
			
                        // 执行多参方法
			Object result = invokeMuliParaMethod(object, method, paras, proxyBeanFactory);
                        // 创建bean
			creatBean(result, returnType, beanName, proxyBeanFactory);
		}
	}

上面List中放的是BeanMethodDefination,这里有必要说下他  五个成员 + 构造方法 + get和set

	private Method method;
	private Object object;
	private Class<?> returnType;
	private Parameter[] parameters;
	private String beanName;

处理扫描到的Bean 

	private static void invokeBeanMethod(Object object, Method method, 
			ProxyBeanFactory proxyBeanFactory, List<BeanMethodDefination> methodList) 
			throws Exception {
                // 获得方法返回值类型
		Class<?> returnType = method.getReturnType();

                // 需判断,若该方法返回void,无须执行,咱这是要得到Bean!
		if (method.getReturnType().equals(void.class)) {
			return;
		}
    
                // 下面判断方法参数个数,有参应在无参方法全部处理完再处理
                // 所以用到了list
		Bean bean = method.getAnnotation(Bean.class);
		String beanName = bean.name();
		Parameter[] parameters = method.getParameters();
		int count = parameters.length;
		if (count <= 0) {
                        // 无参方法直接执行并创建bean
			Object result = method.invoke(object);
			creatBean(result, returnType, beanName, proxyBeanFactory);
		} else {
			methodList.add(new BeanMethodDefination(method, object, returnType, parameters, beanName));
		}
	}

最后处理多参的Bean,遍历其参数,并设置

	private static Object invokeMuliParaMethod(Object object, Method method,
                         Parameter[] parameters, ProxyBeanFactory proxyBeanFactory) throws Exception {
		int count = parameters.length;
		Object paras[] = new Object[count];
		for (int index = 0; index < count; index++) {
			Parameter parameter = parameters[index];
			String className = parameter.getType().getName();
			FyProxy fyProxy = proxyBeanFactory.getFyProxy(className);
			Object beanObject = fyProxy.getObject();
			if (beanObject != null) {
				paras[index] = parameter;
			}
		}
		return method.invoke(object, paras);
	}

构建出Bean(代理)  

	private static void creatBean(Object result, Class<?> klass, String beanName, ProxyBeanFactory proxyBeanFactory) 
			throws Exception {
		if (result != null) {
			proxyBeanFactory.creatCglibProxy(result);
		} else {
			proxyBeanFactory.creatCglibProxy(klass);
		}
		if (beanName.length() > 0) {
			proxyBeanFactory.addBeanName(klass.getName(), beanName);
		}
	}

注入!!!

当getBean时需要注入

	@SuppressWarnings("unchecked")
	public static <T> T getBean(Class<?> klass) {
		ProxyBeanFactory proxyBeanFactory = new ProxyBeanFactory();
		FyProxy fyProxy = proxyBeanFactory.getFyProxy(klass);
		
		if (!fyProxy.isInjection()) {
			injectBean(proxyBeanFactory, klass, fyProxy.getObject());
		}
		
		return (T) fyProxy.getProxy();	 
	}
	public static void injectBean(ProxyBeanFactory proxyBeanFactory, Class<?> klass, 
                            Object object) {

                // 获得该klass所需要的所有成员
                // 遍历
                // 判断其是否有Autowired注解
                // 有则在ProxyBeanFactory中找到代理,将其设置为已注入(为解决循环依赖问题)
                // 判断该成员的类是否也已经注入
                // 若没有
                // 则递归
                // 最后将对象赋给成员  完成注入!!
		Field[] fields = klass.getDeclaredFields();
		for (Field field : fields) {
			if (!field.isAnnotationPresent(Autowired.class)) {
				continue;
			}
			FyProxy fyProxy = proxyBeanFactory.getFyProxy(klass);
			fyProxy.setInjection(true);
			
			Class<?> beanType = field.getType();
			
			FyProxy fieldProxy = proxyBeanFactory.getFyProxy(beanType);
			if (!fieldProxy.isInjection()) {
				injectBean(proxyBeanFactory, beanType, fieldProxy.getObject());
			}
			field.setAccessible(true);
			try {
				field.set(object, fieldProxy.getObject());
			} catch (IllegalArgumentException | IllegalAccessException e) {
				e.printStackTrace();
			}
		}
	}

InterceptorScanner

扫描并设置Bean的***,当然,要在扫描完Bean后再扫描***

扫描指定包路径,若含有Aspect注解,继续扫描其方法,根据注解信息为目标方法加上该***

	public static void scanInterceptor(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) {
						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 (InstantiationException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}.packageScanner(packageName);
	}

添加***至指定方法的***链中,当然,不同***限制条件不同

当然,若注解中method默认为*,则给目标类中所有方法增加该***

	private static void dealAfterInterceptor(Class<?> klass, Object object, Method method, After after) 
			throws Exception {
		Class<?> returnType = method.getReturnType();
		Class<?> targetClass = after.klass();
		String targetMethodStr = after.method();
		Method targetMethod = targetClass.getDeclaredMethod(targetMethodStr, after.parameterTypes());
		Class<?> targetReturntype = targetMethod.getReturnType();
		if (!returnType.equals(targetReturntype)) {
			throw new WrongOfAfterInterceptorReturnType("后置***(" + method + ")返回值不是" + targetReturntype);
		}
		
		if (targetMethodStr.equals("*")) {
			Method[] methods = targetClass.getDeclaredMethods();
			for (Method targetAllMethod : methods) {
				InterceptorTargetDefination target = new InterceptorTargetDefination(targetClass, targetAllMethod);	
				InterceptorMethodDefination interceptor = new InterceptorMethodDefination(klass, method, object);	
				InterceptorFactory.addAfterInterceptor(target, interceptor);
			}
		} else {		
			InterceptorTargetDefination target = new InterceptorTargetDefination(targetClass, targetMethod);	
			InterceptorMethodDefination interceptor = new InterceptorMethodDefination(klass, method, object);	
			InterceptorFactory.addAfterInterceptor(target, interceptor);
		}
	}

前置

	private static void dealBeforeInterceptor(Class<?> klass, Object object, Method method, Before before) 
			throws Exception {
		Class<?> returnType = method.getReturnType();
		if (!returnType.equals(boolean.class)) {
			throw new WrongOfBeforeInterceptorReturnType("前置***(" + method + ")返回值只能是boolean类型");
		}
		Class<?> targetClass = before.klass();
		
		String targetMethodStr = before.method();
		if (targetMethodStr.equals("*")) {
			Method[] methods = targetClass.getDeclaredMethods();
			for (Method targetMethod : methods) {
				InterceptorTargetDefination target = new InterceptorTargetDefination(targetClass, targetMethod);	
				InterceptorMethodDefination interceptor = new InterceptorMethodDefination(klass, method, object);	
				InterceptorFactory.addBeforeInterceptor(target, interceptor);
			}
		} else {			
			Method targetMethod = targetClass.getDeclaredMethod(before.method(), method.getParameterTypes());
			InterceptorTargetDefination target = new InterceptorTargetDefination(before.klass(), targetMethod);	
			InterceptorMethodDefination interceptor = new InterceptorMethodDefination(klass, method, object);	
			InterceptorFactory.addBeforeInterceptor(target, interceptor);
		}
	}

异常

	private static void dealExceptionInterceptor(Class<?> klass, Object object, Method method, ThrowException throwException) 
			throws Exception {
		Class<?> returnType = method.getReturnType();
		if (!returnType.equals(void.class)) {
			throw new ExceptionInterceptorReturnTypeNotVoid("异常***(" + method + ")返回值不是void类型");
		}
		Class<?>[] parameterTypes = method.getParameterTypes();
		if (parameterTypes.length != 1 || parameterTypes[0].equals(Throwable.class)) {
			throw new WrongOfExceptionInterceptorReturnType("异常***(" + method + ")参数类型必须是Throwable");
		}
		Class<?> targetClass = throwException.klass();
		String targetMethodStr = throwException.method();
		if (targetMethodStr.equals("*")) {
			Method[] methods = targetClass.getDeclaredMethods();
			for (Method targetMethod : methods) {
				InterceptorTargetDefination target = new InterceptorTargetDefination(targetClass, targetMethod);	
				InterceptorMethodDefination interceptor = new InterceptorMethodDefination(klass, method, object);	
				InterceptorFactory.addExceptionInterceptor(target, interceptor);
			}
		} else {	
			Method targetMethod = targetClass.getDeclaredMethod(targetMethodStr, method.getParameterTypes());
			InterceptorTargetDefination target = new InterceptorTargetDefination(throwException.klass(), targetMethod);	
			InterceptorMethodDefination interceptor = new InterceptorMethodDefination(klass, method, object);	
			InterceptorFactory.addExceptionInterceptor(target, interceptor);
		}
	}

以上就是自己实现AOP  IOC的全部内容,当然也有许多不足的地方,往各位多多提意见!

全部评论

相关推荐

11-21 11:26
已编辑
门头沟学院 前端工程师
Apries:这个阶段来说,很厉害很厉害了,不过写的简历确实不是很行,优势删掉吧,其他的还行
点赞 评论 收藏
分享
牛客5655:其他公司的面试(事)吗
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务