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("微软雅黑");
}
}