动态代理–基础–04–AOP
代码位置
https://gitee.com/DanShenGuiZu/learnDemo/tree/master/动态代理/demo1
1、Aop中的代理
- Aop是对JDK代理和CGLIB代理做了一层封装,并且引入了AOP概念
- Aop严格的来说都是动态代理
1.1、Aop的注解
@Aspect
@advice
@joinpoint
@pointCut
@after
@before
1.2、原理
- 如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP,可以强制使用CGLIB实现AOP
- 如果目标对象没有实现了接口,必须采用CGLIB实现AOP,spring会自动在JDK动态代理和CGLIB之间转换
1.2.1、如何强制使用CGLIB实现AOP?
- 添加cglib库:
SPRING_HOME/cglib/*.jar
- 在spring配置文件中加入
<aop:aspectj-autoproxy proxy-target-class="true"/>
2、Aop 源码分析
2.1、代码
public class AOPTest {
public static void main(String[] args) {
ProxyFactory proxyFactory = new ProxyFactory(UserDao.class, new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("invoke 方法");
return null;
}
});
//设置优化
proxyFactory.setOptimize(false);
//得到代理对象
Object proxy = proxyFactory.getProxy();
UserDao userDao = (UserDao) proxy;
userDao.addUser();
}
}
2.2、源码分析
获取代理
- 创建代理类
- 获取代理
创建代理
- 没有激活,
- 设置激活状态是true
- 设置监听功能加强
- 获取aop代理工厂
- 创建代理
获取默认代理工厂
创建aop代理
- 进入if的条件
- optimize(优化)=true:要优化
- isProxyTargetClass=true:对具体类进行代理、
- hasNoUserSuppliedProxyInterfaces=true:没有使用提供的代理接口(SpringProxy)
- 进入if后
- 代理目标不存在:aop配置异常
- 代理目标是接口或者是Proxy的子类:返回jdk动态代理
- 其他情况:返回glib动态代理
- 其他情况:返回jdk动态代理
jdk动态代理源码
- 获取代理接口数组
- 查看方法代理接口中方法是不是equals,hashcode方法
- 创建代理的class对象
JdkDynamicAopProxy中的就是最核心的方法invoke
/**
* Implementation of {@code InvocationHandler.invoke}.
* <p>Callers will see exactly the exception thrown by the target,
* unless a hook method throws an exception.
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Class targetClass = null;
Object target = null;
try {
//是否实现equals和hashCode,没有实现就不代理。因为JDK代理会默认代理这两个方法
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
//没有实现equals方法就返回
return equals(args[0]);
}
if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
//没有实现hashCode方法就返回
return hashCode();
}
//不能代理adviser接口和子接口自身
if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
//代理类和ThreadLocal绑定
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
//获取目标对象
target = targetSource.getTarget();
if (target != null) {
targetClass = target.getClass();
}
//
//得到拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
//如果没有定义拦截器链。直接调用方法不进行代理
if (chain.isEmpty()) {
// 直接调用方法
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);
}
else {
//创建ReflectiveMethodInvocation对象
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
//执行拦截器链。通过proceed递归调用
retVal = invocation.proceed();
}
//方法返回类型
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
//如果返回值是this 直接返回代理对象本身
retVal = proxy;
} else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException("Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
ReflectiveMethodInvocation这个类的proceed()方法
负责递归调用所有的拦截的织入
@Override
@Nullable
public Object proceed() throws Throwable {
// list的索引从-1开始。
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {\
//所有interceptor都被执行完了 ,直接执行原方法
return invokeJoinpoint();
}
//获取拦加强方法(是before或after等织入,不受在list中的位置影响)
Object interceptorOrInterceptionAdvice =this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
//........
// 调用我们实现接口(MethodInterceptor)的invoke方法
//
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
要实现织入,只要控制织入的代码和调用proceed方法的位置
在Spring中的before织入
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {
private MethodBeforeAdvice advice;
public Object invoke(MethodInvocation mi) throws Throwable {
//调用before实际代码
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
//继续迭代
return mi.proceed();
}
afterRuturning是这样实现的:
public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {
private final AfterReturningAdvice advice;
public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed();
//只要控制和mi.proceed()调用的位置关系就可以实现任何状态的织入效果
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}
包含上述一个before织入和一个afterReturning织入的流程图:
利用迭代的思想很简单实现了链式调用
public interface MethodInterceptor {
Object invoke(Invocation invocation);
public static class beforeMethodInterceptor implements MethodInterceptor{
@Override
public Object invoke(Invocation invocation) {
System.out.println("开始前方法");
return invocation.proceed();
}
}
public static class AfterRuturningMethodInterceptor implements MethodInterceptor{
@Override
public Object invoke(Invocation invocation) {
Object proceed = invocation.proceed();
System.out.println("结束后方法");
return proceed;
}
}
}
}
public interface Invocation {
Object proceed();
public static class MethodInvocation implements Invocation{
private List<MethodInterceptor> list;
private int index=-1;
private int ListSize=0;
public MethodInvocation(List<MethodInterceptor> list) {
this.list=list;
ListSize=list.size();
}
@Override
public Object proceed() {
if(index==ListSize-1){
System.out.println("执行方法实体");
return "返回值";
}
MethodInterceptor methodInterceptor = list.get(++index);
//递归调用方法
return methodInterceptor.invoke(this);
}
}
}
3、AOP的简单实现
3.1、设计
3.1.1、核心思路
- 维护一个映射表MAP(切点方法,增强方法列表)
- 使用cglib对切点进行增强。
- 返回cglib的代理实例
3.1.2、细节
- 扫描要被增强的bean
- 扫描所有切面
- 构建映射表MAP(切点方法,增强方法列表)
- 构建bean容器,该容器包含切面信息
3.2、代码
package feizhou.demo1.business.demo.myAop.annotation;
/**
*
* 切点类型
* @author <a href="920786312@qq.com">周飞</a>
* @since 2024/4/28 10:24
*/
public enum MyPointCutType {
//前置通知
BEFORE,
//后置通知
AFTER,
}
package feizhou.demo1.business.demo.myAop.annotation;
import org.springframework.core.annotation.AliasFor;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定义切点注解
*
* @author <a href="920786312@qq.com">周飞</a>
* @return
* @since 2024/4/28 10:24
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyPointCut {
/**
* 包路径的切点表达式
* @param
* @return java.lang.String[]
* @author <a href="920786312@qq.com">周飞</a>
* @since 2024/5/1 22:16
*/
String[] packagePath() default {};
//切点类型
MyPointCutType type();
}
package feizhou.demo1.business.demo.myAop.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定义切面注解
* 定义在类上,那么该类就是一个切面,切面有定义对那些方法进行增强
* @author <a href="920786312@qq.com">周飞</a>
* @since 2024/4/27 22:51
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyAspect {
}
package feizhou.demo1.business.demo.myAop.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定义实例化注解
* 定义在类上,那么这个类就是加入到AOP增强的bean 容器中
* @author <a href="920786312@qq.com">周飞</a>
* @since 2024/4/27 22:55
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyComponent {
}
package feizhou.demo1.business.demo.myAop.example;
import feizhou.demo1.business.demo.myAop.annotation.MyAspect;
import feizhou.demo1.business.demo.myAop.annotation.MyComponent;
import feizhou.demo1.business.demo.myAop.annotation.MyPointCut;
import feizhou.demo1.business.demo.myAop.annotation.MyPointCutType;
@MyAspect
@MyComponent
public class MyBeanAspect {
/**
* 定义扫描包路径和切点类型为前置通知
*
* @author <a href="920786312@qq.com">周飞</a>
* @since 2024/4/28 10:29
*/
// 前置通知
@MyPointCut(type = MyPointCutType.BEFORE,
packagePath = {"public int feizhou.demo1.business.demo.myAop.example.Teacher.getName(java.lang.String)",
"public void feizhou.demo1.business.demo.myAop.example.User.addUser(java.lang.String, int)"})
public static void logBefore() {
System.out.println("前置通知--->静态方法");
}
// 后置通知
@MyPointCut(type = MyPointCutType.AFTER,
packagePath = {"public int feizhou.demo1.business.demo.myAop.example.Teacher.getName(java.lang.String)",
"public void feizhou.demo1.business.demo.myAop.example.User.addUser(java.lang.String, int)"})
public static void logAfter() {
System.out.println("后置通知--->静态方法");
}
// 后置通知
@MyPointCut(type = MyPointCutType.AFTER,
packagePath = {"public int feizhou.demo1.business.demo.myAop.example.Teacher.getName(java.lang.String)",
"public void feizhou.demo1.business.demo.myAop.example.User.addUser(java.lang.String, int)"})
public void logAfter2() {
System.out.println("后置通知--->非静态方法");
}
}
package feizhou.demo1.business.demo.myAop.example;
import feizhou.demo1.business.demo.myAop.annotation.MyComponent;
@MyComponent
public class Teacher {
public void getName(String name) {
System.out.println("当前老师名称是:" + name);
}
}
package feizhou.demo1.business.demo.myAop.example;
import feizhou.demo1.business.demo.myAop.annotation.MyComponent;
@MyComponent
public class User {
public String addUser(String name, int age) {
String s = "新增用户:" + name + ",年龄:" + age;
System.out.println(s);
return s;
}
}
package feizhou.demo1.business.demo.myAop;
import feizhou.demo1.business.demo.myAop.annotation.MyPointCut;
import feizhou.demo1.business.demo.myAop.annotation.MyPointCutType;
import lombok.Data;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Map;
/**
* @Description 增强bean
* @Author feizhou
* @Date 2024/5/1 14:46
* @Verson 1.0
**/
@Data
public class ExpandBean {
//切点class类对象
private Class<?> pointCutClazz;
//切面class类对象
private Class<?> aspectClazz;
/**
* 被增强的实例,这个实例可能被增强,也可能没有被增强
*
* @author <a href="920786312@qq.com">周飞</a>
* @since 2024/5/1 14:47
*/
private Object instance;
/**
* 扩展类对应的切面
*
* @author <a href="920786312@qq.com">周飞</a>
* @since 2024/5/1 20:25
*/
private ExpandBeanAspect expandBeanAspect;
public ExpandBean(Class<?> pointCutClazz, Class<?> aspectClazz) {//构造方法
this.pointCutClazz = pointCutClazz;
this.aspectClazz = aspectClazz;
}
/**
* cglib 动态代理,实现MethodInterceptor方法
*
* @author <a href="920786312@qq.com">周飞</a>
* @return
* @since 2024/5/1 15:33
*/
// Method interceptor for bean proxy class.
//代理bean的获取
private static class BeanProxyInterceptor implements MethodInterceptor {
ExpandBeanFactory beanFactory;
ExpandBeanAspect expandBeanAspect;
public BeanProxyInterceptor(ExpandBeanFactory beanFactory, ExpandBeanAspect expandBeanAspect) {
this.beanFactory = beanFactory;
this.expandBeanAspect = expandBeanAspect;
}
private void invokeAspectMethod(Method method) throws Exception {
if (Modifier.isStatic(method.getModifiers())) {//静态方法
method.invoke(null);
} else {//非静态方法,无参构造
method.invoke(beanFactory.getBean(method.getDeclaringClass()));
}
}
@Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
ExpandBeanAspect.AspectMethods aspects = expandBeanAspect.getPointCutAspects().get(method);
if (aspects == null) {
// No aspect for this method.
return proxy.invokeSuper(obj, args);
}
//前置通知方法
// for (Map.Entry<Class, ExpandBeanAspect.AspectMethods> entry : aspects.entrySet()) {
// Class aspectBeanId = entry.getKey();
// ExpandBeanAspect.AspectMethods aspectMethods = entry.getValue();
// Invoke aspect "before" methods.
for (Method m : aspects.beforeMethods) {
invokeAspectMethod(m);
}
// }
// 业务方法
Object re = proxy.invokeSuper(obj, args);
// //后置通知方法
// Invoke aspect "after" methods.
for (Method m : aspects.afterMethods) {
invokeAspectMethod(m);
}
return re;
}
}
/**
* 获取bean的增强实例
*
* @param beanFactory
* @return java.lang.Object
* @author <a href="920786312@qq.com">周飞</a>
* @since 2024/5/1 16:16
*/
public Object getInstance(ExpandBeanFactory beanFactory) throws Exception {
//如果就返回
if (this.instance != null) {
return this.instance;
}
synchronized (this) {
if (this.instance != null) {
return this.instance;
}
//如果切面不存在
if (expandBeanAspect == null) {
// 如果切面不存在,通过反射返回一个简单类
this.instance = pointCutClazz.getConstructor(new Class[]{}).newInstance();
} else {
// cglib 代理增强
Enhancer eh = new Enhancer();
eh.setSuperclass(pointCutClazz);
eh.setCallback(new BeanProxyInterceptor(beanFactory, expandBeanAspect));
//返回代理类
this.instance = eh.create();
}
return this.instance;
}
}
/**
* 添加切面方法
*
* @param pointcutMethod 切点方法
* @param myPointCut 切点注解
* @param aspectMethod 切面方法
* @return void
* @author <a href="920786312@qq.com">周飞</a>
* @since 2024/5/1 17:55
*/
public void addAspectMethod(Method pointcutMethod, MyPointCut myPointCut, Method aspectMethod) {
Map<Method, ExpandBeanAspect.AspectMethods> pointCutAspects = expandBeanAspect.getPointCutAspects();
// Find pointcut method.
ExpandBeanAspect.AspectMethods aspectMethods = pointCutAspects.get(pointcutMethod);
if (aspectMethods == null) {
//切面方法不存在,创建切面方法
aspectMethods = new ExpandBeanAspect.AspectMethods();
pointCutAspects.put(pointcutMethod, aspectMethods);
}
//补充切面方法的数据
if (myPointCut.type() == MyPointCutType.BEFORE) {
aspectMethods.beforeMethods.add(aspectMethod);
} else if (myPointCut.type() == MyPointCutType.AFTER) {
aspectMethods.afterMethods.add(aspectMethod);
}
}
}
package feizhou.demo1.business.demo.myAop;
import feizhou.demo1.business.demo.myAop.annotation.MyPointCut;
import feizhou.demo1.business.demo.myAop.annotation.MyPointCutType;
import lombok.Getter;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 扩展bean的切面
* 一个扩展bean 只有一个切面
*
* @author <a href="920786312@qq.com">周飞</a>
* @since 2024/4/28 14:13
*/
public class ExpandBeanAspect {
/**
* 定义切点方法、对应的切面方法
* Map from pointcut method to aspects. Each aspect is a also a map, from aspect bean to aspect
* Map<切点方法,Map<beanId,切面方法>>
*
* @author <a href="920786312@qq.com">周飞</a>
* @since 2024/4/29 12:29
*/
@Getter
private Map<Method, AspectMethods> pointCutAspects = new HashMap<>();
/**
* 切面方法
*
* @author <a href="920786312@qq.com">周飞</a>
* @since 2024/4/29 12:29
*/
public static class AspectMethods {
public List<Method> beforeMethods = new ArrayList<>();
public List<Method> afterMethods = new ArrayList<>();
}
}
package feizhou.demo1.business.demo.myAop;
import com.google.common.reflect.ClassPath;
import feizhou.demo1.business.demo.myAop.annotation.MyAspect;
import feizhou.demo1.business.demo.myAop.annotation.MyComponent;
import feizhou.demo1.business.demo.myAop.annotation.MyPointCut;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 扩展bean的工厂
*
* @author <a href="920786312@qq.com">周飞</a>
* @since 2024/4/27 22:49
*/
public class ExpandBeanFactory {
//bean容器
public Map<Class, ExpandBean> beans = new HashMap();
public ExpandBeanFactory(String[] packages) {//构造方法
scanPackages(packages);
}
/**
* 获取bean,这个bean是增强的bean
*
* @return java.lang.Object
* @author <a href="920786312@qq.com">周飞</a>
* @since 2024/4/27 22:49
*/
public Object getBean(Class clazz) throws Exception {
ExpandBean expandBean = beans.get(clazz);
if (expandBean != null) {
return expandBean.getInstance(this);
} else {
throw new RuntimeException("No such bean: " + clazz);
}
}
/**
* 扫描包
*
* @param packages
* @return void
* @author <a href="920786312@qq.com">周飞</a>
* @since 2024/4/27 22:51
*/
private void scanPackages(String[] packages) {
for (String pkg : packages) {
scanBeansInPackage(pkg);
}
}
/**
* 扫描包
*
* @param pkg 包路径
* @author <a href="920786312@qq.com">周飞</a>
* @since 2024/5/1 21:50
*/
private void scanBeansInPackage(String pkg) {
ClassPath cp;
try {
cp = ClassPath.from(getClass().getClassLoader());
} catch (IOException e) {
e.printStackTrace();
//有异常就退出
return;
}
//先加载对应的bean
for (ClassPath.ClassInfo ci : cp.getTopLevelClasses(pkg)) {
//加载类
Class<?> clazz = ci.load();
// 加载有MyComponent注解的类到bean 容器里面去
Annotation componentAnnotation = clazz.getAnnotation(MyComponent.class);
if (componentAnnotation != null) {
// Add new Bean.
beans.put(clazz, new ExpandBean(clazz, null));
}
}
//再加载切面
for (ClassPath.ClassInfo ci : cp.getTopLevelClasses(pkg)) {
//加载类
Class<?> clazz = ci.load();
// 加载有MyAspect注解的类到切面中
Annotation componentAnnotation = clazz.getAnnotation(MyAspect.class);
if (componentAnnotation != null) {
//切面方法
for (Method aspectMethod : clazz.getMethods()) {
addBeanAspects(aspectMethod);
}
}
}
}
/**
* 添加切面
*
* @param aspectMethod
* @return void
* @author <a href="920786312@qq.com">周飞</a>
* @since 2024/5/1 21:43
*/
private void addBeanAspects(Method aspectMethod) {
// 获取切点注解
MyPointCut myPointCut = aspectMethod.getDeclaredAnnotation(MyPointCut.class);
if (myPointCut != null) {
//获取切点方法
for (Method pointCutMethod : parsePointCutExpr(myPointCut.packagePath())) {
//获取切点类名称
Class pointCutClazz = pointCutMethod.getDeclaringClass();
ExpandBean expandBean = beans.get(pointCutClazz);
//获取切面
ExpandBeanAspect expandBeanAspect = expandBean.getExpandBeanAspect();
if (expandBeanAspect == null) { //切面不存在就创建
expandBeanAspect = new ExpandBeanAspect();
//切点的beanId
expandBean.setExpandBeanAspect(expandBeanAspect);
expandBean.setAspectClazz(aspectMethod.getDeclaringClass());
}
//切面添加切点方法
expandBean.addAspectMethod(pointCutMethod, myPointCut, aspectMethod);
}
}
}
/**
* 解析并获取切点方法
*
* @param packagePaths 包路径数组
* @return java.util.List<java.lang.reflect.Method>
* @author <a href="920786312@qq.com">周飞</a>
* @since 2024/5/1 21:49
*/
private List<Method> parsePointCutExpr(String[] packagePaths) {
List<Method> result = new ArrayList<Method>();
//正则表达式
Pattern r = Pattern.compile("^public \\s*[\\w\\$]+ \\s*(([\\w\\$]+\\.)*([\\w\\$]+))\\.([\\w\\$]+)\\s*\\((.*)\\)$");
//以分号分割切点
for (String point : packagePaths) {
Matcher m = r.matcher(point.trim());
if (!m.find()) {
System.out.println("Can't parse cut point expression: " + point);
continue;
}
String pointCutClassPath = m.group(1);
String pointCutMethodName = m.group(4);
String pointCutMethodArgsList = m.group(5);
try {
//class
Class<?> clazz = Class.forName(pointCutClassPath);
//方法参数数组
String[] argTypeListStr = pointCutMethodArgsList.split(",");
//参数类型的class数组
Class[] argTypes = new Class[argTypeListStr.length];
for (int i = 0; i < argTypeListStr.length; i++) {
argTypes[i] = getArgClass(argTypeListStr[i].trim());
}
result.add(clazz.getMethod(pointCutMethodName, argTypes));
} catch (ClassNotFoundException e) {
e.printStackTrace();
continue;
} catch (NoSuchMethodException e) {
e.printStackTrace();
continue;
}
}
return result;
}
//返回参数类型的class对象
private Class getArgClass(String str) throws ClassNotFoundException {
if (str.equals("int")) {
return int.class;
} else if (str.equals("long")) {
return long.class;
} else if (str.equals("short")) {
return short.class;
} else if (str.equals("float")) {
return float.class;
} else if (str.equals("double")) {
return double.class;
} else if (str.equals("byte")) {
return byte.class;
} else if (str.equals("char")) {
return char.class;
} else if (str.equals("boolean")) {
return boolean.class;
} else {
return Class.forName(str);
}
}
}
package feizhou.demo1.business.demo.myAop;
/**
* @ClassName: AOPTest
* @Description 请描述下该类是做什么的
* @Author feizhou
* @Date 2024/4/27 21:37
* @Verson 1.0
**/
import feizhou.demo1.business.demo.myAop.example.Teacher;
import feizhou.demo1.business.demo.myAop.example.User;
import java.util.*;
import java.lang.reflect.*;
public class AOPTest {
public static void main(String[] args) throws Exception {
testBeanFactory();
}
public static void testBeanFactory() throws Exception {
//通过包路径获取工厂
ExpandBeanFactory factory = new ExpandBeanFactory(new String[]{"feizhou.demo1.business.demo.myAop.example"});
for (Map.Entry<Class, ExpandBean> entry1 : factory.beans.entrySet()) {
ExpandBean expandBean = entry1.getValue();
System.out.println("切点类: " + expandBean.getPointCutClazz());
System.out.println(" 切面类: " + expandBean.getAspectClazz());
ExpandBeanAspect expandBeanAspect = expandBean.getExpandBeanAspect();
Map<Method, ExpandBeanAspect.AspectMethods> pointCutAspects=null;
if(expandBeanAspect!=null){
pointCutAspects = expandBeanAspect.getPointCutAspects();
}
if(pointCutAspects==null){
continue;
}
for (Map.Entry<Method, ExpandBeanAspect.AspectMethods> entry2 : pointCutAspects.entrySet()) {
System.out.println(" 切点方法: " + entry2.getKey().getName());
for (Method method : entry2.getValue().beforeMethods) {
System.out.println(" 切面before方法: " + method.getName());
}
for (Method method : entry2.getValue().afterMethods) {
System.out.println(" 切面after方法: " + method.getName());
}
}
}
System.out.println();
System.out.println("---------teacher.getName------------");
Teacher teacher = (Teacher) factory.getBean(Teacher.class);
teacher.getName("小周");
System.out.println();
System.out.println("----------user.addUser-----------");
User user = (User) factory.getBean(User.class);
user.addUser("小明", 100);
}
}
输出:
切点类: class feizhou.demo1.business.demo.myAop.example.Teacher
切面类: class feizhou.demo1.business.demo.myAop.example.MyBeanAspect
切点方法: getName
切面before方法: logBefore
切面after方法: logAfter
切面after方法: logAfter2
切点类: class feizhou.demo1.business.demo.myAop.example.MyBeanAspect
切面类: null
切点类: class feizhou.demo1.business.demo.myAop.example.User
切面类: class feizhou.demo1.business.demo.myAop.example.MyBeanAspect
切点方法: addUser
切面before方法: logBefore
切面after方法: logAfter
切面after方法: logAfter2
---------teacher.getName------------
前置通知--->静态方法
当前老师名称是:小周
后置通知--->静态方法
后置通知--->非静态方法
----------user.addUser-----------
前置通知--->静态方法
新增用户:小明,年龄:100
后置通知--->静态方法
后置通知--->非静态方法