public class JdkProxyDemo {
interface Foo{
void foo();
}
static class Target implements Foo{
@Override
public void foo() {
System.out.println("target foo");
}
}
// jdk 只能针对接口代理
public static void main(String[] args) {
Target target = new Target();
ClassLoader loader = JdkProxyDemo.class.getClassLoader(); // 用来加载运行时动态生成的字节码
Foo foo = (Foo)Proxy.newProxyInstance(loader, new Class[]{Foo.class}, (p, method, args1) -> {
System.out.println("before...");
// 反射调用 方法.invoke(目标、参数)
Object invoke = method.invoke(target, args1);
System.out.println("after...");
return invoke;
});
foo.foo();
}
}
public class CglibProxyDemo {
static class Target{
public void foo(){
System.out.println("target foo");
}
}
// cglib的目标对象和方法不能被final修饰,因为代理类和目标类的父子关系,jdk代理类和目标类的同级关系
public static void main(String[] params) {
Target target = new Target();
Target target1 = (Target) Enhancer.create(Target.class, (MethodInterceptor) (p, method, args, methodProxy) -> {
System.out.println("before...");
// method.invoke(target,args); // 用方法反射目标
// methodProxy.invokeSuper(p,args); // methodProxy内部没有调用反射,需要代理
Object invoke = methodProxy.invoke(target, args); // methodProxy内部没有调用反射,需要目标
System.out.println("after..");
return invoke;
});
target1.foo();
}
}
public class ProxySourceDemo {
interface Foo {
void foo();
int bar();
}
static class Target implements Foo {
@Override
public void foo() {
System.out.println("target foo");
}
@Override
public int bar() {
System.out.println("target bar");
return 100;
}
}
interface InvocationHandler {
Object invoke(Object proxy, Method method,Object[] args) throws Throwable;
}
public static void main(String[] args) {
Foo foo = new $Proxy0(new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理增强");
Object result = method.invoke(new Target(), args);
return result;
}
});
foo.foo();
foo.bar();
}
}
public class $Proxy0 implements ProxySourceDemo.Foo {
private ProxySourceDemo.InvocationHandler invocationHandler;
public $Proxy0(ProxySourceDemo.InvocationHandler invocationHandler) {
this.invocationHandler = invocationHandler;
}
@Override
public void foo() {
try {
invocationHandler.invoke(this,foo,new Object[0]);
} catch (RuntimeException | Error e) {
throw e;
}catch (Throwable e){
throw new UndeclaredThrowableException(e);
}
}
@Override
public int bar() {
try {
return (int) invocationHandler.invoke(this,bar,new Object[0]);
} catch (RuntimeException | Error e) {
throw e;
}catch (Throwable e){
throw new UndeclaredThrowableException(e);
}
}
static Method foo;
static Method bar;
static {
try {
foo = ProxySourceDemo.Foo.class.getMethod("foo");
bar = ProxySourceDemo.Foo.class.getMethod("bar");
} catch (NoSuchMethodException e) {
throw new NoSuchMethodError(e.getMessage());
}
}
}
jdk反射优化 前16次都是通过反射调用 性能比较低,17次的时候已经把反射调用变成正常调用,代价是为了一个方法的反射调用生成了一个代理类
public class Target {
public void save0(){
System.out.println("save0()");
}
public void save1(int i){
System.out.println("save1(int)");
}
public void save2(long i){
System.out.println("save2(long)");
}
}
public class Proxy extends Target{
private MethodInterceptor methodInterceptor;
public Proxy(MethodInterceptor methodInterceptor) {
this.methodInterceptor = methodInterceptor;
}
static Method save0;
static Method save1;
static Method save2;
static MethodProxy save0Proxy;
static MethodProxy save1Proxy;
static MethodProxy save2Proxy;
static {
try {
save0 = Target.class.getMethod("save0");
save1 = Target.class.getMethod("save1",int.class);
save2 = Target.class.getMethod("save2",long.class);
// c1=目标类 c2=代理类
save0Proxy = MethodProxy.create(Target.class,Proxy.class,"()V","save0","save0Super");
save1Proxy = MethodProxy.create(Target.class,Proxy.class,"(I)V","save1","save1Super");
save2Proxy = MethodProxy.create(Target.class,Proxy.class,"(J)V","save2","save2Super");
} catch (NoSuchMethodException e) {
throw new UndeclaredThrowableException(e);
}
}
// 原始功能的方法
public void save0Super(){
super.save0();
}
public void save1Super(int i){
super.save1(i);
}
public void save2Super(long l){
super.save2(l);
}
// 增强功能的方法
@Override
public void save0() {
try {
methodInterceptor.intercept(this,save0,new Object[0],save0Proxy);
} catch (Throwable e) {
throw new UndeclaredThrowableException(e);
}
}
@Override
public void save1(int i) {
try {
methodInterceptor.intercept(this,save1,new Object[]{i},save1Proxy);
} catch (Throwable e) {
throw new UndeclaredThrowableException(e);
}
}
@Override
public void save2(long l) {
try {
methodInterceptor.intercept(this,save2,new Object[]{l},save2Proxy);
} catch (Throwable e) {
throw new UndeclaredThrowableException(e);
}
}
}
public class CglibSourceDemo {
public static void main(String[] args) {
Proxy proxy = new Proxy(new MethodInterceptor() {
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("cglib代理增强");
Object invoke = method.invoke(new Target(),args);
return invoke;
}
});
proxy.save0();
proxy.save1(1);
proxy.save2(1l);
}
}
无反射调用原理
public class SpringProxyDemo {
public static void main(String[] args) {
/*
两个切面概念:
aspect=
通知1(advice) + 切点1 (pointcut)
通知2(advice) + 切点2 (pointcut)
通知3(advice) + 切点3 (pointcut)
advisor = 更细粒度点切面,包含一个通知和切点
*/
// 准备好切点
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression("execution(* foo())");
// 准备好通知
MethodInterceptor advice = new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("before..");
Object proceed = invocation.proceed();
System.out.println("after...");
return proceed;
}
};
// 准备好切面
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut,advice);
// 创建代理
/*
ProxyConfig
proxyTargetClass:false 目标实现接口 使用jdk实现
proxyTargetClass:false 目标没有实现接口 使用cglib实现
proxyTargetClass:true 总是使用cglib实现
*/
Target1 target1 = new Target1();
ProxyFactory factory = new ProxyFactory();
factory.addAdvisor(advisor);
factory.setTarget(target1);
// factory.setInterfaces(target1.getClass().getInterfaces());
factory.setProxyTargetClass(true);
T1 t1 = (T1) factory.getProxy();
System.out.println(t1.getClass());
t1.foo();
t1.bar();
}
interface T1 {
void foo();
void bar();
}
static class Target1 implements T1 {
@Override
public void foo() {
System.out.println("foo....");
}
@Override
public void bar() {
System.out.println("bar....");
}
}
}
package com.liubo.spring.a09;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator;
import org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator;
import org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
/**
* @author lb
* @date 2022/12/31 4:36 下午
*/
public class AnnotationAwareAspectJAutoProxyCreatorDemo {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
GenericApplicationContext context = new GenericApplicationContext();
context.registerBean("config", Config.class);
context.registerBean("aspect", Aspect1.class);
context.registerBean(ConfigurationClassPostProcessor.class);
/*
AnnotationAwareAspectJAutoProxyCreator作用:
1.找到容器中所有的切面,如果是高级切面会转换成低级切面
2.根据切面创建代理对象
*/
context.registerBean(AnnotationAwareAspectJAutoProxyCreator.class);
/*
创建--->(*)依赖注入--->初始化(*)
a.代理的创建时机
1.初始化之后(无循环依赖)
2.实例创建后,依赖注入前(有循环依赖时)并暂存于二级缓存
b.依赖注入与初始化不应该被增强,任应被施加于原始对象
*/
context.refresh();
AnnotationAwareAspectJAutoProxyCreator creator = context.getBean(AnnotationAwareAspectJAutoProxyCreator.class);
/*
creator.findEligibleAdvisors(Target1.class, "target1"):找到有资格的Advisors
creator.wrapIfNecessary(new Target1(),"target1","target1"):内部调用findEligibleAdvisors,只要返回集合不为空,则表示需要创建代理
*/
Method method = AbstractAdvisorAutoProxyCreator.class.getDeclaredMethod("findEligibleAdvisors", Class.class, String.class);
method.setAccessible(true);
List<Advisor> advisors = (List<Advisor>) method.invoke(creator, Target1.class, "target1");
for (Advisor advisor : advisors) {
System.out.println(advisor);
}
Method method2 = AbstractAutoProxyCreator.class.getDeclaredMethod("wrapIfNecessary", Object.class, String.class, Object.class);
method2.setAccessible(true);
Object o1 = method2.invoke(creator, new Target1(), "target1", "target1");
System.out.println(o1.getClass());
Object o2 = method2.invoke(creator, new Target2(), "target2", "target2");
System.out.println(o2.getClass());
}
static class Target1 {
public void foo() {
System.out.println("Target1 foo ....");
}
}
static class Target2 {
public void bar() {
System.out.println("Target2 bar ....");
}
}
@Aspect // 高级切面类
static class Aspect1 {
@Before("execution(* foo())")
public void before() {
System.out.println("before1 ....");
}
@Before("execution(* foo())")
public void after() {
System.out.println("after1 ....");
}
}
@Configuration
static class Config {
@Bean // 低级切面 切点+通知
public Advisor advisor(MethodInterceptor advice) {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression("execution(* foo())");
return new DefaultPointcutAdvisor(pointcut, advice);
}
@Bean
public MethodInterceptor advice() {
return new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("before2..");
Object proceed = invocation.proceed();
System.out.println("after2...");
return proceed;
}
};
}
}
}
高级切面转低级切面过程
public class A18 {
static class Aspect {
@Before("execution(* foo())")
public void before1() {
System.out.println("before1");
}
@Before("execution(* foo())")
public void before2() {
System.out.println("before2");
}
public void after() {
System.out.println("after");
}
@AfterReturning("execution(* foo())")
public void afterReturning() {
System.out.println("afterReturning");
}
@AfterThrowing("execution(* foo())")
public void afterThrowing(Exception e) {
System.out.println("afterThrowing " + e.getMessage());
}
@Around("execution(* foo())")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
try {
System.out.println("around...before");
return pjp.proceed();
} finally {
System.out.println("around...after");
}
}
}
static class Target {
public void foo() {
System.out.println("target foo");
}
}
@SuppressWarnings("all")
public static void main(String[] args) throws Throwable {
AspectInstanceFactory factory = new SingletonAspectInstanceFactory(new Aspect());
// 1. 高级切面转低级切面类
List<Advisor> list = new ArrayList<>();
for (Method method : Aspect.class.getDeclaredMethods()) {
if (method.isAnnotationPresent(Before.class)) {
// 解析切点
String expression = method.getAnnotation(Before.class).value();
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression(expression);
// 通知类
AspectJMethodBeforeAdvice advice = new AspectJMethodBeforeAdvice(method, pointcut, factory);
// 切面
Advisor advisor = new DefaultPointcutAdvisor(pointcut, advice);
list.add(advisor);
} else if (method.isAnnotationPresent(AfterReturning.class)) {
// 解析切点
String expression = method.getAnnotation(AfterReturning.class).value();
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression(expression);
// 通知类
AspectJAfterReturningAdvice advice = new AspectJAfterReturningAdvice(method, pointcut, factory);
// 切面
Advisor advisor = new DefaultPointcutAdvisor(pointcut, advice);
list.add(advisor);
} else if (method.isAnnotationPresent(Around.class)) {
// 解析切点
String expression = method.getAnnotation(Around.class).value();
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression(expression);
// 通知类
AspectJAroundAdvice advice = new AspectJAroundAdvice(method, pointcut, factory);
// 切面
Advisor advisor = new DefaultPointcutAdvisor(pointcut, advice);
list.add(advisor);
}
}
for (Advisor advisor : list) {
System.out.println(advisor);
}
/*
@Before 前置通知会被转换为下面原始的 AspectJMethodBeforeAdvice 形式, 该对象包含了如下信息
a. 通知代码从哪儿来
b. 切点是什么
c. 通知对象如何创建, 本例共用同一个 Aspect 对象
类似的通知还有
1. AspectJAroundAdvice (环绕通知)
2. AspectJAfterReturningAdvice
3. AspectJAfterThrowingAdvice (环绕通知)
4. AspectJAfterAdvice (环绕通知)
*/
// 2. 通知统一转换为环绕通知 MethodInterceptor
/*
其实无论 ProxyFactory 基于哪种方式创建代理, 最后干活(调用 advice)的是一个 MethodInvocation 对象
a. 因为 advisor 有多个, 且一个套一个调用, 因此需要一个调用链对象, 即 MethodInvocation
b. MethodInvocation 要知道 advice 有哪些, 还要知道目标, 调用次序如下
将 MethodInvocation 放入当前线程
|-> before1 ----------------------------------- 从当前线程获取 MethodInvocation
| |
| |-> before2 -------------------- | 从当前线程获取 MethodInvocation
| | | |
| | |-> target ------ 目标 advice2 advice1
| | | |
| |-> after2 --------------------- |
| |
|-> after1 ------------------------------------
c. 从上图看出, 环绕通知才适合作为 advice, 因此其他 before、afterReturning 都会被转换成环绕通知
d. 统一转换为环绕通知, 体现的是设计模式中的适配器模式
- 对外是为了方便使用要区分 before、afterReturning
- 对内统一都是环绕通知, 统一用 MethodInterceptor 表示
此步获取所有执行时需要的 advice (静态)
a. 即统一转换为 MethodInterceptor 环绕通知, 这体现在方法名中的 Interceptors 上
b. 适配如下
- MethodBeforeAdviceAdapter 将 @Before AspectJMethodBeforeAdvice 适配为 MethodBeforeAdviceInterceptor
- AfterReturningAdviceAdapter 将 @AfterReturning AspectJAfterReturningAdvice 适配为 AfterReturningAdviceInterceptor
*/
Target target = new Target();
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(target);
proxyFactory.addAdvice(ExposeInvocationInterceptor.INSTANCE); // 准备把 MethodInvocation 放入当前线程
proxyFactory.addAdvisors(list);
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
List<Object> methodInterceptorList = proxyFactory.getInterceptorsAndDynamicInterceptionAdvice(Target.class.getMethod("foo"), Target.class);
for (Object o : methodInterceptorList) {
System.out.println(o);
}
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
// 3. 创建并执行调用链 (环绕通知s + 目标)
MethodInvocation methodInvocation = new ReflectiveMethodInvocation(
null, target, Target.class.getMethod("foo"), new Object[0], Target.class, methodInterceptorList
);
methodInvocation.proceed();
/*
学到了什么
a. 无参数绑定的通知如何被调用
b. MethodInvocation 编程技巧: 拦截器、过滤器等等实现都与此类似
c. 适配器模式在 Spring 中的体现
*/
}
}