首页 > 科技 > 正文

Spring AOP底层原理分析
2019-10-04 10:50:24   来源:东方头条   

1.aop的实现有很多种方式:

1.1aspecth静态代理实现aop

1.2com.java.proxy.cglib cglib动态代理实现aop

利用拦截器(拦截器必须实现InvocationHanlder)加上反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。

1.3com.java.proxy.dynamicporxy jdk实现动态代理aop

利用ASM开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

何时使用JDK还是CGLIB?

1)如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP。

2)如果目标对象实现了接口,可以强制使用CGLIB实现AOP。

3)如果目标对象没有实现了接口,必须采用CGLIB库,Spring会自动在JDK动态代理和CGLIB之间转换。

AOP底层原理分析:

1.首先启动SpringAop时,会使用该@EnableAspectJAutoProxy注解;

2.将@Import(AspectJAutoProxyRegistrar)注入到SpringIOC容器中;

3.AspectJAutoProxyRegistrar中会注册对象

eanId: org.springframework.aop.config.internalAutoProxyCreator

BeanClass:AnnotationAwareJAutoProxyCreator

4.AnnotationAwareJAutoProxyCreator最为核心:使用后置通知在bean的对象初始化的时候,实现对代理对象的增强;祖宗:AbstracAutoProxyCreator 祖宗有BeanPostProcessor.

5.被代理对象在初始化的时候,AbstractAutoProxyCreator经过这样的一个类拦截,判断该被代理对象是否有被实现过的接口,如果有实现过的接口就是有jdk动态代理,如果没有实现接口则使用cglib动态代理。自定义注解:

package com.ww.service;

import java.lang.annotation.*;

@Documented

@Target(ElementType.METHOD)

@Retention(RetentionPolicy.RUNTIME)

public @interface SaveLog {

public String name() default "ww";

public String value() default "ceshi";

}

@GetMapping("/{id}")

@SaveLog(name="db",value="test")

public String findById(@PathVariable Long id){

System.out.println("*****************************"+id+"****************************");

User user = userRepository.getOne(id);

return user.toString();

}

package com.ww.aop;

import com.alibaba.fastjson.JSON;

import com.ww.service.SaveLog;

import org.aspectj.lang.JoinPoint;

import org.aspectj.lang.ProceedingJoinPoint;

import org.aspectj.lang.annotation.*;

import org.springframework.context.annotation.EnableAspectJAutoProxy;

import org.springframework.stereotype.Component;

import java.lang.reflect.Modifier;

@Aspect

@Component

@EnableAspectJAutoProxy

public class MyLogAop {

//aop拦截自定义注解

@Pointcut(value="@annotation(com.ww.service.SaveLog)")

private void myLogAop(){

System.out.println("aop执行了!!!");

}

@Before(value = "myLogAop()")

public void beFore(JoinPoint joinPoint){

Object aThis = joinPoint.getThis();

System.out.println(JSON.toJSONString(aThis));

System.out.println("aop之前执行了!!!");

}

@Around("myLogAop()")

private void around(ProceedingJoinPoint joinPoint) {

Object target = joinPoint.getTarget().getClass().getName();

System.out.println("调用者+"+target);

System.out.println("******拦截前的逻辑******");

System.out.println("目标方法名为:" + joinPoint.getSignature().getName());

System.out.println("目标方法所属类的简单类名:" + joinPoint.getSignature().getDeclaringType().getSimpleName());

System.out.println("目标方法所属类的类名:" + joinPoint.getSignature().getDeclaringTypeName());

System.out.println("目标方法声明类型:" + Modifier.toString(joinPoint.getSignature().getModifiers()));

//获取传入目标方法的参数

Object[] args = joinPoint.getArgs();

for (int i = 0; i < args.length; i++) {

System.out.println("第" + (i + 1) + "个参数为:" + args[i]);

}

System.out.println("被代理的对象:" + joinPoint.getTarget());

System.out.println("代理对象自己:" + joinPoint.getThis());

System.out.println("拦截的注解的参数:");

Signature signature = joinPoint.getSignature();

MethodSignature methodSignature = (MethodSignature) signature;

Method method = methodSignature.getMethod();

if (method != null) {

SaveLog saveLog = method.getAnnotation(SaveLog.class);

System.out.println("saveLog--name:"+saveLog.name());

System.out.println("saveLog--value:"+saveLog.value());

}

System.out.println("环绕开始执行了!!!");

try {

joinPoint.proceed();

} catch (Throwable throwable) {

System.out.println("aop around异常处理!!!");

throwable.printStackTrace();

}

System.out.println("环绕结束执行了!!!");

}

@Around("myLogAop()&&@annotation(saveLog)")

private void around(ProceedingJoinPoint joinPoint,SaveLog saveLog) {

Object target = joinPoint.getTarget().getClass().getName();

System.out.println("调用者+"+target);

System.out.println("******拦截前的逻辑******");

System.out.println("目标方法名为:" + joinPoint.getSignature().getName());

System.out.println("目标方法所属类的简单类名:" + joinPoint.getSignature().getDeclaringType().getSimpleName());

System.out.println("目标方法所属类的类名:" + joinPoint.getSignature().getDeclaringTypeName());

System.out.println("目标方法声明类型:" + Modifier.toString(joinPoint.getSignature().getModifiers()));

//获取传入目标方法的参数

Object[] args = joinPoint.getArgs();

for (int i = 0; i < args.length; i++) {

System.out.println("第" + (i + 1) + "个参数为:" + args[i]);

}

System.out.println("被代理的对象:" + joinPoint.getTarget());

System.out.println("代理对象自己:" + joinPoint.getThis());

System.out.println("拦截的注解的参数:");

System.out.println(saveLog.name());

System.out.println(saveLog.value());

System.out.println("环绕开始执行了!!!");

try {

joinPoint.proceed();

} catch (Throwable throwable) {

System.out.println("aop around异常处理!!!");

throwable.printStackTrace();

}

System.out.println("环绕结束执行了!!!");

}

@AfterThrowing("myLogAop()")

private void afterThrowing(JoinPoint joinPoint){

System.out.println("aop异常处理!!!");

}

}

springbean生命周期

基jdk实现aop:

package com.java.proxy.dynamicporxy;

iport java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

import java.util.HashMap;

import java.util.Map;

public class CachedProviderHandler implements InvocationHandler{

private Map<String, Object> cached = new HashMap<String, Object>();

private Object target;

public CachedProviderHandler(Object target) {

this.target = target;

}

/**

* invoke方法可以处理target的所有方法,这里用if判断只处理了getXXX()方法,增加了缓存功能。

*/

@Override

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

System.out.println("使用动态代理了!");

Class<?>[] types = method.getParameterTypes();

if(method.getName().matches("get.+") && types.length == 1 && types[0] == String.class) {

System.out.println("getXXX()方法,使用缓存");

String key = (String)args[0];

Object value = cached.get(key);

if(value == null) {

value = method.invoke(target, args);

cached.put(key, value);

}

return value;

}

return method.invoke(target, args);

}

}

工厂类ProviderFactory.java

package com.java.proxy.dynamicporxy;

import java.lang.reflect.Proxy;

import com.java.proxy.FontProvider;

import com.java.proxy.FontProviderFromDisk;

public class ProviderFactory {

public static FontProvider getFontProvider() {

Class<FontProvider> targetClass = FontProvider.class;

return (FontProvider)Proxy.newProxyInstance(targetClass.getClassLoader(), new Class[]{targetClass},

new CachedProviderHandler(new FontProviderFromDisk()));

}

}

cglib动态代理实现aoppackage com.java.proxy.cglib;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;

import net.sf.cglib.proxy.MethodInterceptor;

import net.sf.cglib.proxy.MethodProxy;

public class CGLibProxy implements MethodInterceptor{

@SuppressWarnings("unchecked")

public <T> T getProxy(Class<T> cls) {

return (T) Enhancer.create(cls, this);

}

@Override

public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {

System.out.println("使用cglib1");

Object result = proxy.invokeSuper(obj, args);

System.out.println("使用cglib2");

return result;

}

}

测试类

package com.java.proxy.cglib;

import com.java.proxy.FontProviderFromDisk;

public class Business {

public static void main(String[] args) {

CGLibProxy cgLibProxy = new CGLibProxy();

FontProviderFromDisk proxy = cgLibProxy.getProxy(FontProviderFromDisk.class);

proxy.printName("微软雅黑");

}

}

相关热词搜索:底层 原理 分析 Spring AOP

上一篇:中兴 Blade 20 现身 FCC:5000mAh+ “浴霸”三摄
下一篇:最后一页

济宁知名律师   电话:0531-80961678
手机:18053115917   微信:18053115917   QQ:709581498   邮箱:709581498@qq.com
网站地图 (XML地图 / 百度地图