当前位置: 首页 > news >正文

邢台企业网站建设服务国内永久免费crm听说

邢台企业网站建设服务,国内永久免费crm听说,保险微网站制作,网站如何转做appSpring之AOP底层源码解析 1、动态代理 代理模式的解释#xff1a;为其他对象提供一种代理以控制对这个对象的访问#xff0c;增强一个类中的某个方法#xff0c;对程序进行扩展。 举个例子 public class UserService {public void test() {System.out.println(test.…Spring之AOP底层源码解析 1、动态代理 代理模式的解释为其他对象提供一种代理以控制对这个对象的访问增强一个类中的某个方法对程序进行扩展。 举个例子 public class UserService {public void test() {System.out.println(test...);} }此时我们 new 一个 UserService 对象然后执行 test() 方法结果是显而易见的。 那如果我们现在想在不修改 UserService 类的源码前提下给 test() 方法增加额外的逻辑那么就可以使用动态代理机制来创建 UserService 对象了比如 public static void main(String[] args) {// 被代理对象UserService target new UserService();// 通过cglib技术Enhancer enhancer new Enhancer();// 设置要代理的类enhancer.setSuperclass(UserService.class);// 定义额外的逻辑也就是代理逻辑enhancer.setCallbacks(new Callback[]{new MethodInterceptor() {/**** param o 代理对象* param method 当前正在执行的方法* param objects 方法所需要的参数* param methodProxy* return* throws Throwable*/Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println(before...);// 执行被代理对象的原始方法Object result methodProxy.invoke(target, objects);// Object result methodProxy.invokeSuper(o, objects); 这种方式也可以System.out.println(after...);return result;}}});// 动态代理所创建出来的UserService代理对象UserService userService (UserService) enhancer.create();// 执行这个userService的test方法时就会额外执行一些其他逻辑userService.test();}得到的都是 UserService 对象但是执行 test() 方法时的效果却不一样了这就是代理所带来的效果。 上面是通过 cglib 来实现的动态代理对象的创建是基于子父类的被代理类UserService是父类代理类是子类代理对象就是代理类的实例对象代理类是由 cglib 创建的对于程序员来说不用关心。 除了 cglib 技术JDK 本身也提供了一种创建代理对象的动态代理机制但是它只能代理接口也就是 UserService 得先有一个接口才能利用 JDK 动态代理机制来生成一个代理对象比如 public interface UserInterface {public void test();}public class UserService implements UserInterface {public void test() {System.out.println(test...);} }利用 JDK 动态代理来生成一个代理对象 public static void main(String[] args) {// 被代理对象UserService target new UserService();/*** UserInterface接口的代理对象* 注意第一个参数可以是任意类的类加载器而第二个参数必须是代理对象的类型*/Object proxy Proxy.newProxyInstance(UserService.class.getClassLoader(), new Class[]{UserInterface.class}, new InvocationHandler() {Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println(before...);// 通过反射机制调用被代理对象的原始方法Object result method.invoke(target, args);System.out.println(after...);return result;}});UserInterface userService (UserInterface) proxy;userService.test();}如果你把 new Class[]{UserInterface.class}替换成 new Class[]{UserService.class}那么代码会直接报错 表示一定要是个接口。 由于这个限制所以产生的代理对象的类型是 UserInterface而不是 UserService这是需要注意的。 2、ProxyFactory 上面我们介绍了两种动态代理技术那么在 Spring 中进行了封装封装出来的类叫做 ProxyFactory表示是创建代理对象的一个工厂使用起来会比上面的更加方便比如 public static void main(String[] args) {// 被代理对象UserService target new UserService();// 创建代理对象工厂ProxyFactory proxyFactory new ProxyFactory();// 设置要代理的目标类proxyFactory.setTarget(target);/*** 注意如果没有加上下面这行代码那么默认走的是cglib动态代理* 而如果我们设置了接口那么走的就是jdk动态代理*/proxyFactory.setInterfaces(UserInterface);// 设置代理逻辑MethodInterceptor表示方法拦截器proxyFactory.addAdvice(new MethodInterceptor() {Overridepublic Object invoke(MethodInvocation invocation) throws Throwable {System.out.println(before...);Object result invocation.proceed();System.out.println(after...);return result;}});// 通过代理对象工厂获取代理对象UserInterface userService (UserInterface) proxyFactory.getProxy();userService.test();}通过 ProxyFactory我们可以不再关心到底是用 cglib 还是 JDK 动态代理了ProxyFactory 会帮助我们去判断如果 UserService 实现了接口那么ProxyFactory 底层就会采用 JDK 动态代理如果没有实现接口就会采用 cglib 动态代理。上面的代码就是由于 UserService 实现了 UserInterface 接口所以最后产生的代理对象是 UserInterface 类型。 3、Advice的分类 1、Before Advice方法调用前执行 public class XiexuBeforeAdvice implements MethodBeforeAdvice {Overridepublic void before(Method method, Object[] args, Object target) throws Throwable {System.out.println(方法调用前执行);} }2、After Returning Advice方法 Return 后执行 public class XiexuAfterReturningAdvice implements AfterReturningAdvice {/*** param returnValue 执行完被代理方法之后的返回值* param method 被代理方法* param args 方法所需要的参数* param target 被代理对象* throws Throwable*/Overridepublic void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {System.out.println(方法return后执行);}}3、After Throwing Advice方法抛异常后执行 public class XiexuThrowsAdvice implements ThrowsAdvice {/*** NullPointerException ex当方法抛出的异常类型为NullPointerException类型时才会调用该方法*/public void afterThrowing(Method method, Object[] args, Object target, NullPointerException ex) {System.out.println(方法抛出异常后执行);}}4、After Advice方法执行完之后执行不管当前方法有没有抛出异常这个 Advice 方法都会执行 5、Around Advice这是功能最强大的 Advice可以自定义执行顺序 public class XiexuAroundAdvice implements MethodInterceptor {NullableOverridepublic Object invoke(NotNull MethodInvocation invocation) throws Throwable {System.out.println(方法执行Around前);// 执行被代理方法Object proceed invocation.proceed();System.out.println(方法执行Around后);return proceed;} }3.1、MethodInterceptor链 除了Around advice其他 advice 在执行完各自的逻辑代码后都会自动调用 proceed() 去执行被代理方法而每次调用 proceed() 就会去看还有没有设置其他的 advice如果有就会继续执行其他 advice 的代理逻辑。 这里就是用到了「责任链」设计模式。 public static void main(String[] args) {// 被代理对象UserService target new UserService();// 代理对象工厂ProxyFactory proxyFactory new ProxyFactory();// 设置目标对象proxyFactory.setTarget(target);proxyFactory.addAdvice(new XiexuBeforeAdvice());proxyFactory.addAdvice(new XiexuAroundAdvice());proxyFactory.addAdvice(new XiexuAroundAdvice());// 获取代理对象UserService proxy (UserService) proxyFactory.getProxy();proxy.test(); // 执行这行代码的时候底层就会去执行invocation.proceed()}proceed() 方法源码 OverrideNullablepublic Object proceed() throws Throwable {/*** currentInterceptorIndex初始值为-1每调用一个Interceptor就会加1* 当调用完了最后一个Interceptor后就会执行被代理的方法*/if (this.currentInterceptorIndex this.interceptorsAndDynamicMethodMatchers.size() - 1) {// 执行被代理的方法点进invokeJoinpoint()看看return invokeJoinpoint();}// currentInterceptorIndex初始值为-1Object interceptorOrInterceptionAdvice this.interceptorsAndDynamicMethodMatchers.get(this.currentInterceptorIndex);/*** 如果当前interceptor是InterceptorAndDynamicMethodMatcher则先进行匹配匹配成功后再调用该interceptor* 如果没有匹配则递归调用proceed()方法调用下一个interceptor*/if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {InterceptorAndDynamicMethodMatcher dm (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;Class? targetClass (this.targetClass ! null ? this.targetClass : this.method.getDeclaringClass());// 动态匹配根据方法参数进行匹配if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {return dm.interceptor.invoke(this);} else {// 不匹配则执行下一个MethodInterceptorreturn proceed();}} else {/*** 直接调用MethodInterceptor传入this在内部会再次调用proceed()方法进行递归* 比如MethodBeforeAdviceInterceptor*/return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);}}4、Advisor的理解 跟 Advice 类似的还有一个 Advisor 的概念一个 Advisor 是由一个 Pointcut 和一个 Advice 组成的通过 Pointcut 可以指定需要被代理的逻辑比如一个 UserService 类中有两个方法按上面 ProxyFactory 的例子这两个方法都会被代理、被增强那么我们现在可以通过 Advisor来控制具体代理哪一个方法比如 public class Test {public static void main(String[] args) {// 被代理对象UserService target new UserService();// 代理对象工厂ProxyFactory proxyFactory new ProxyFactory();// 设置目标对象proxyFactory.setTarget(target);proxyFactory.addAdvisor(new PointcutAdvisor() {/*** Pointcut可以去定义我们的代理逻辑要应用到哪个方法或哪个类上面* return*/Overridepublic Pointcut getPointcut() {return new StaticMethodMatcherPointcut() {Overridepublic boolean matches(Method method, Class? targetClass) {// 表示只有test()方法才需要走代理逻辑return method.getName().equals(test);}};}/*** Advice只是表示一段代理逻辑* return*/Overridepublic Advice getAdvice() {return new XiexuAroundAdvice();}/*** 这个方法可以忽略* return*/Overridepublic boolean isPerInstance() {return false;}});// 获取代理对象UserInterface userService (UserInterface) proxyFactory.getProxy();userService.test();}}上面代码表示产生的代理对象只有在执行 test() 这个方法时才会被增强才会执行额外的逻辑而在执行其他方法时是不会被增强的。 5、创建代理对象的方式 上面介绍了 Spring 中所提供的 ProxyFactory、Advisor、Advice、PointCut 等技术来实现代理对象的创建但是我们在使用 Spring 时并不会直接这么去使用 ProxyFactory比如说我们希望 ProxyFactory 所产生的代理对象能直接就是 Bean能直接从 Spring 容器中得到 UserSerivce 的代理对象而这些 Spring 都是支持的只不过作为开发者的我们肯定得先告诉 Spring哪些类需要被代理代理逻辑是什么。 5.1、ProxyFactoryBean // 将产生的代理对象成为一个BeanBeanpublic ProxyFactoryBean userService() {UserService userService new UserService();// 创建ProxyFactoryBean对象ProxyFactoryBean proxyFactoryBean new ProxyFactoryBean();// 设置要代理的对象proxyFactoryBean.setTarget(userService);// 代理逻辑proxyFactoryBean.addAdvice(new MethodInterceptor() {Overridepublic Object invoke(MethodInvocation invocation) throws Throwable {System.out.println(before...);Object result invocation.proceed();System.out.println(after...);return result;}});return proxyFactoryBean;}通过这种方式来定义一个 UserService 的 Bean并且是经过了 AOP 的。但是这种方式只能针对某一个 Bean。它是一个 FactoryBean所以利用的就是FactoryBean 技术间接地将 UserService 的代理对象作为了 Bean。 ProxyFactoryBean 还有额外的功能比如可以把某个 Advice 或 Advisor 定义成为 Bean然后在 ProxyFactoryBean 中进行设置 Beanpublic MethodInterceptor XiexuAroundAdvice() {return new MethodInterceptor() {Overridepublic Object invoke(MethodInvocation invocation) throws Throwable {System.out.println(before...);Object result invocation.proceed();System.out.println(after...);return result;}};}Beanpublic ProxyFactoryBean userService() {// 被代理对象UserService userService new UserService();ProxyFactoryBean proxyFactoryBean new ProxyFactoryBean();// 设置目标对象proxyFactoryBean.setTarget(userService);proxyFactoryBean.setInterceptorNames(XiexuAroundAdvice);return proxyFactoryBean;}5.2、BeanNameAutoProxyCreator ProxyFactoryBean 得自己指定被代理的对象那么我们可以通过 BeanNameAutoProxyCreator 指定某个 bean 的名字来对该 bean 进行代理 Beanpublic MethodInterceptor XiexuAroundAdvice() {return new MethodInterceptor() {Overridepublic Object invoke(MethodInvocation invocation) throws Throwable {System.out.println(before...);Object result invocation.proceed();System.out.println(after...);return result;}};}Beanpublic BeanNameAutoProxyCreator beanNameAutoProxyCreator() {BeanNameAutoProxyCreator beanNameAutoProxyCreator new BeanNameAutoProxyCreator();beanNameAutoProxyCreator.setBeanNames(userSe*);beanNameAutoProxyCreator.setInterceptorNames(XiexuAroundAdvice);beanNameAutoProxyCreator.setProxyTargetClass(true);return beanNameAutoProxyCreator;}通过 BeanNameAutoProxyCreator 可以对批量的 Bean 进行 AOP并且指定了代理逻辑指定了一个 InterceptorName也就是一个 Advice前提条件是这个 Advice 也得是一个 Bean这样 Spring 才能找到但是 BeanNameAutoProxyCreator 的缺点很明显它只能根据 beanName 来指定想要代理的 Bean。 5.3、DefaultAdvisorAutoProxyCreator public class AppConfig {/*** 定义一个Advisor类型的Bean** return*/Beanpublic DefaultPointcutAdvisor defaultPointcutAdvisor() {NameMatchMethodPointcut pointcut new NameMatchMethodPointcut();pointcut.addMethodName(test);DefaultPointcutAdvisor defaultPointcutAdvisor new DefaultPointcutAdvisor();defaultPointcutAdvisor.setPointcut(pointcut);defaultPointcutAdvisor.setAdvice(new XiexuAfterReturningAdvice());return defaultPointcutAdvisor;}Beanpublic DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator new DefaultAdvisorAutoProxyCreator();return defaultAdvisorAutoProxyCreator;}}通过 DefaultAdvisorAutoProxyCreator 会直接去找所有 Advisor 类型的 Bean然后根据 Advisor 中的 PointCut 和 Advice 信息确定要代理的 Bean 以及代理逻辑。 通过这种方式我们得依靠某一个类来实现定义我们的 Advisor或者 Advice或者 Pointcut那么这个步骤能不能更加简化一点呢 答案是可以的我们可以通过注解的方式进行简化 比如我们可以只定义一个类然后通过在类中的方法上加上某些注解来定义 PointCut 以及 Advice比如 AspectComponentpublic class XiexuAspect {Before(execution(public void cn.xx.UserService.test()))public void xiexuBefore(JoinPoint joinPoint) {System.out.println(xiexuBefore);}}通过上面这个类我们就直接定义好了所要代理的方法通过一个表达式以及代理逻辑被 Before 修饰的方法简单明了这样对于 Spring 来说它要做的就是来解析这些注解了解析之后得到对应的 Pointcut 对象、Advice 对象生成 Advisor 对象扔进 ProxyFactory 中进而产生对应的代理对象具体怎么解析这些注解就是 EnableAspectJAutoProxy 注解所要做的事情了后面详细分析。 6、对Spring AOP的理解 OOP 表示面向对象编程是一种编程思想AOP 表示面向切面编程也是一种编程思想而我们上面所描述的就是 Spring 为了让程序员更加方便的做到面向切面编程所提供的技术支持换句话说就是 Spring 提供了一套机制可以让我们更加容易的进行 AOP所以这套机制我们也可以称之为 Spring AOP。 但是值得注意的是上面所提供的注解的方式来定义 Pointcut 和 AdviceSpring 并不是首创首创是 AspectJ而且也不仅仅只有 Spring 提供了一套机制来支持 AOP还有比如 JBoss 4.0、aspectwerkz 等技术都提供了对于 AOP 的支持。而刚刚说的注解的方式Spring 是依赖了 AspectJ 的换句话说Spring 是直接把 AspectJ 中所定义的那些注解直接拿过来用自己没有再重新定义了不过也仅仅只是把注解的定义复制过来了每个注解具体底层是怎么解析的还是 Spring 自己做的所以我们在使用 Spring 时如果你想用 Before、Around 等注解是需要单独引入 AspectJ 相关 jar 包的比如 compile group: org.aspectj, name: aspectjrt, version: 1.9.5 compile group: org.aspectj, name: aspectjweaver, version: 1.9.5值得注意的是AspectJ 是在编译时对字节码进行了修改是直接在 UserService 类对应的字节码中进行增强的也就是可以理解为是在编译时就会去解析Before 这些注解然后得到代理逻辑加入到被代理类中的字节码中去的所以如果想用 AspectJ 技术来生成代理对象 是需要用单独的 AspectJ 编译器的。我们在项目中很少这么使用我们仅仅只是用了 Before 这些注解而我们在启动 Spring 的过程中Spring 会去解析这些注解然后利用动态代理机制生成代理对象的。 IDEA 中使用 AspectJhttps://blog.csdn.net/gavin_john/article/details/80156963 7、AOP中的概念 上面我们已经提到 Advisor、Advice、PointCut 等概念了还有一些其他的概念首先关于 AOP 中的概念本身是比较难理解的Spring 官网上是这么说的 Let us begin by defining some central AOP concepts and terminology. These terms are not Spring-specific. Unfortunately, AOP terminology is not particularly intuitive. However, it would be even more confusing if Spring used its own terminology 意思是AOP 中的这些概念并不是 Spring 特有的而且不幸的是AOP 中的概念不是特别直观的如果 Spring 重新定义自己的那可能会导致更加混乱。 1、Aspect表示切面比如被 Aspect 注解的类就是切面可以在切面中去定义 Pointcut、Advice 等等。 2、Join point表示连接点表示一个程序在执行过程中的一个点比如一个方法的执行被代理方法、一个异常的处理在 Spring AOP 中一个连接点通常表示一个方法的执行。 3、Advice表示通知表示在一个特定连接点上所采取的动作。Advice 分为不同的类型后面详细讨论在很多 AOP 框架中包括 Spring会用Interceptor 拦截器来实现 Advice并且会在连接点周围维护一个 Interceptor 链。 4、Pointcut表示切点用来匹配一个或多个连接点Advice 与切点表达式是关联在一起的Advice 将会执行在和切点表达式所匹配的连接点上。 5、Introduction可以使用 DeclareParents 来给所匹配的类添加一个接口并指定一个默认实现。 6、Target object目标对象也就是被代理对象。 7、AOP Proxy表示代理工厂用来创建代理对象的在 Spring Framework 中要么是 JDK 动态代理要么是 CGLIB 动态代理。 8、Weaving表示织入表示创建代理对象的动作这个动作可以发生在编译时期比如 Aspejctj也可以发生在运行时期比如 Spring AOP。 8、Advice在Spring AOP中对应的API 上面说到的 AspjectJ 中的注解其中有五个是用来定义 Advice 的表示代理逻辑以及执行时机 1、Before 2、AfterReturning 3、AfterThrowing 4、After 5、Around 我们前面也提到过Spring 自己也提供了类似的实现类 1、接口MethodBeforeAdvice继承了接口BeforeAdvice 2、接口AfterReturningAdvice继承了接口AfterAdvice 3、接口ThrowsAdvice继承了接口AfterAdvice 4、接口AfterAdvice继承了接口Advice 5、接口MethodInterceptor继承了接口Interceptor Spring 会把这五个注解解析成对应的 Advice 类 1、BeforeAspectJMethodBeforeAdvice实际上就是一个 MethodBeforeAdvice 2、AfterReturningAspectJAfterReturningAdvice实际上就是一个 AfterReturningAdvice 3、AfterThrowingAspectJAfterThrowingAdvice实际上就是一个 MethodInterceptor 4、AfterAspectJAfterAdvice实际上就是一个 MethodInterceptor 5、AroundAspectJAroundAdvice实际上就是一个 MethodInterceptor 9、TargetSource的使用 在我们日常的 AOP 中被代理对象就是 Bean 对象是由 BeanFactory 给我们创建出来的但是 Spring AOP 中提供了 TargetSource 机制可以让我们自定义逻辑来创建被代理对象。 比如之前提到的 Lazy 注解当加在属性上时会产生一个代理对象并赋值给这个属性产生代理对象的代码为 /*** 创建Lazy懒加载的代理对象** param descriptor* param beanName* return*/protected Object buildLazyResolutionProxy(final DependencyDescriptor descriptor, final Nullable String beanName) {// 获取Spring的Bean工厂BeanFactory beanFactory getBeanFactory();Assert.state(beanFactory instanceof DefaultListableBeanFactory, BeanFactory needs to be a DefaultListableBeanFactory);final DefaultListableBeanFactory dlbf (DefaultListableBeanFactory) beanFactory;/*** 创建TargetSource对象*/TargetSource ts new TargetSource() {Overridepublic Class? getTargetClass() {return descriptor.getDependencyType();}Overridepublic boolean isStatic() {return false;}/*** Lazy的效果* 当属性上有Lazy注解刚开始进行依赖注入时该属性是被赋了一个代理对象* 当你真正用到该属性时这时候才会根据当前属性的类型和名字去BeanFactory中找到对应的Bean这时候才会真正去执行对应Bean的原方法。* 当set方法的参数有Lazy注解时同理。* return*/Overridepublic Object getTarget() {SetString autowiredBeanNames (beanName ! null ? new LinkedHashSet(1) : null);// 根据属性的类型和名字去Bean工厂找被代理的对象Object target dlbf.doResolveDependency(descriptor, beanName, autowiredBeanNames, null);if (target null) {Class? type getTargetClass();if (Map.class type) {return Collections.emptyMap();} else if (List.class type) {return Collections.emptyList();} else if (Set.class type || Collection.class type) {return Collections.emptySet();}throw new NoSuchBeanDefinitionException(descriptor.getResolvableType(), Optional dependency not present for lazy injection point);}if (autowiredBeanNames ! null) {for (String autowiredBeanName : autowiredBeanNames) {if (dlbf.containsBean(autowiredBeanName)) {dlbf.registerDependentBean(autowiredBeanName, beanName);}}}// 找到被代理的对象直接返回return target;}Overridepublic void releaseTarget(Object target) {}};// 创建ProxyFactory对象ProxyFactory pf new ProxyFactory();// 设置被代理对象为TargetSourcepf.setTargetSource(ts);Class? dependencyType descriptor.getDependencyType();if (dependencyType.isInterface()) {pf.addInterface(dependencyType);}// 返回一个代理对象return pf.getProxy(dlbf.getBeanClassLoader());}这段代码就利用了 ProxyFactory 来生成代理对象以及使用了 TargetSource以达到代理对象在执行某个方法时会去调用 TargetSource 的 getTarget() 方法得到一个被代理对象。 10、ProxyFactory选择CGLIB或JDK动态代理的原理 ProxyFactory 在生成代理对象之前需要先决定到底是使用 JDK 动态代理还是 CGLIB 动态代理 Overridepublic AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {/*** config指的是我们在外面创建的ProxyFactory对象* NativeDetector.inNativeImage()当前Spring项目是不是在GraalVM虚拟机上运行的如果是则使用JDK动态代理创建代理对象* config.isOptimize()如果isOptimize为true则会使用cglib动态代理创建代理对象因为Spring认为cglib比jdk动态代理要快* config.isProxyTargetClass()要代理的是不是一个类如果为true则使用cglib动态代理创建代理对象* hasNoUserSuppliedProxyInterfaces(config)当前ProxyFactory对象有没有去添加接口addInterface* 如果添加了则返回false并使用JDK动态代理创建代理对象如果没有添加接口则返回true并使用cglib动态代理创建代理对象*/if (!NativeDetector.inNativeImage() /*** 类似于* ProxyFactory proxyFactory new ProxyFactory();* proxyFactory.setOptimize(true);* proxyFactory.setProxyTargetClass(true);* 如果添加了proxyFactory.addInterface();* 那么hasNoUserSuppliedProxyInterfaces(config)为false如果没有添加则为true*/(config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {// 获取被代理类的类型Class? targetClass config.getTargetClass();if (targetClass null) {throw new AopConfigException(TargetSource cannot determine target class: Either an interface or a target is required for proxy creation.);}/*** targetClass.isInterface()如果被代理的类是一个接口* 举个例子* ProxyFactory proxyFactory new ProxyFactory();* proxyFactory.setTargetClass(UserInterface.class);* 这样的话就表示被代理类是一个接口* Proxy.isProxyClass(targetClass)当前所设置的被代理类是不是已经进行过JDK动态代理而生成的代理类*/if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {/*** 使用jdk动态代理创建代理对象*/return new JdkDynamicAopProxy(config);}/*** 返回Cglib创建的代理对象*/return new ObjenesisCglibAopProxy(config);} else {/*** 使用jdk动态代理创建代理对象*/return new JdkDynamicAopProxy(config);}}11、代理对象创建过程 11.1、JdkDynamicAopProxy 1、在构造 JdkDynamicAopProxy 对象时会先拿到被代理对象自己所实现的接口并且额外增加 SpringProxy、Advised、DecoratingProxy 三个接口组合成一个 Class[]并赋值给 proxiedInterfaces 属性 2、并且检查这些接口中是否定义了equals()、hashcode()方法 3、执行 Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this)得到代理对象JdkDynamicAopProxy 作为 InvocationHandler代理对象在执行某个方法时会进入到 JdkDynamicAopProxy 的 invoke() 方法中 12、代理对象执行过程 1、在使用 ProxyFactory 创建代理对象之前需要往 ProxyFactory 中先添加 Advisor 2、代理对象在执行某个方法时会把 ProxyFactory 中的 Advisor 拿出来和当前正在执行的方法进行匹配筛选 3、把和当前正在执行的方法所匹配的 Advisor 适配成 MethodInterceptor 4、把和当前方法匹配的 MethodInterceptor 链以及被代理对象、代理对象、代理类、当前 Method 对象、方法参数封装成 MethodInvocation 对象 5、调用 MethodInvocation 的 proceed() 方法开始执行各个 MethodInterceptor 以及被代理对象的对应方法 6、按顺序调用每个 MethodInterceptor 的 invoke() 方法并且会把 MethodInvocation 对象传入 invoke() 方法 7、直到执行完最后一个 MethodInterceptor 了就会调用 invokeJoinpoint() 方法从而执行被代理对象的当前方法 12.1、各注解对应的MethodInterceptor 1、Before 对应的是 AspectJMethodBeforeAdvice在进行动态代理时会把 AspectJMethodBeforeAdvice 转成 MethodBeforeAdviceInterceptor 先执行 advice 对应的方法再执行 MethodInvocation 的 proceed()会执行下一个 Interceptor如果没有下一个 Interceptor 了会执行 target 对应的方法 2、After 对应的是 AspectJAfterAdvice直接实现了 MethodInterceptor 先执行 MethodInvocation 的 proceed()会执行下一个 Interceptor如果没有下一个 Interceptor 了会执行 target 对应的方法再执行 advice 对应的方法 3、Around 对应的是 AspectJAroundAdvice直接实现了 MethodInterceptor 直接执行 advice 对应的方法由 Around 自己决定要不要继续往后面调用 4、AfterThrowing 对应的是 AspectJAfterThrowingAdvice直接实现了 MethodInterceptor 先执行 MethodInvocation的 proceed()会执行下一个 Interceptor如果没有下一个 Interceptor 了会执行 target 对应的方法如果上面抛了 Throwable那么则会执行 advice 对应的方法 5、AfterReturning 对应的是 AspectJAfterReturningAdvice在进行动态代理时会把 AspectJAfterReturningAdvice 转成 AfterReturningAdviceInterceptor 先执行 MethodInvocation 的 proceed()会执行下一个 Interceptor如果没有下一个 Interceptor 了会执行 target 对应的方法执行上面的方法后得到最终的方法的返回值再执行 Advice 对应的方法 13、AbstractAdvisorAutoProxyCreator DefaultAdvisorAutoProxyCreator 的父类是 AbstractAdvisorAutoProxyCreator。 AbstractAdvisorAutoProxyCreator 非常强大以及重要只要 Spring 容器中存在这个类型的 Bean就相当于开启了 AOPAbstractAdvisorAutoProxyCreator实际上就是一个 BeanPostProcessor所以在创建某个 Bean 时就会进入到它对应的生命周期方法中比如在某个 Bean 初始化之后会调用wrapIfNecessary() 方法进行 AOP底层逻辑是AbstractAdvisorAutoProxyCreator 会找到所有的 Advisor然后判断当前这个 Bean 是否存在某个 Advisor 与之匹配根据 Pointcut如果匹配就表示当前这个 Bean 有对应的切面逻辑需要进行AOP需要产生一个代理对象。 14、EnableAspectJAutoProxy 这个注解主要就是往 Spring 容器中添加了一个 AnnotationAwareAspectJAutoProxyCreator 类型的Bean。 AspectJAwareAdvisorAutoProxyCreator 继承了 AbstractAdvisorAutoProxyCreator重写了 findCandidateAdvisors() 方法AbstractAdvisorAutoProxyCreator 只能找到所有 Advisor 类型的 Bean 对象但是 AspectJAwareAdvisorAutoProxyCreator 除了可以找到所有 Advisor 类型的 Bean 对象还能把 Aspect 注解所标注的 Bean 中的 Before 等注解及方法进行解析并生成对应的 Advisor 对象。 Aspect Component public class XxAspect {Before(execution(public void cn.xx.UserService.test()))public void xiexuBefore(JoinPoint joinPoint) {System.out.println(xiexuBefore);}}所以我们可以这样理解 EnableAspectJAutoProxy其实就是向 Spring 容器中添加了一个 AbstractAdvisorAutoProxyCreator 类型的Bean从而开启了 AOP并且还会解析 Before 等注解并生成 Advisor。 15、Spring中AOP原理流程图 https://www.processon.com/view/link/5faa4ccce0b34d7a1aa2a9a5
文章转载自:
http://www.morning.smkxm.cn.gov.cn.smkxm.cn
http://www.morning.csjps.cn.gov.cn.csjps.cn
http://www.morning.zsyqg.cn.gov.cn.zsyqg.cn
http://www.morning.gkgr.cn.gov.cn.gkgr.cn
http://www.morning.fnssm.cn.gov.cn.fnssm.cn
http://www.morning.jwfqq.cn.gov.cn.jwfqq.cn
http://www.morning.dkgtr.cn.gov.cn.dkgtr.cn
http://www.morning.jfymz.cn.gov.cn.jfymz.cn
http://www.morning.qbmjf.cn.gov.cn.qbmjf.cn
http://www.morning.kwksj.cn.gov.cn.kwksj.cn
http://www.morning.qinhuangdjy.cn.gov.cn.qinhuangdjy.cn
http://www.morning.24vy.com.gov.cn.24vy.com
http://www.morning.pmbcr.cn.gov.cn.pmbcr.cn
http://www.morning.ysfj.cn.gov.cn.ysfj.cn
http://www.morning.snygg.cn.gov.cn.snygg.cn
http://www.morning.ktcfl.cn.gov.cn.ktcfl.cn
http://www.morning.clbzy.cn.gov.cn.clbzy.cn
http://www.morning.qlsbz.cn.gov.cn.qlsbz.cn
http://www.morning.rxyz.cn.gov.cn.rxyz.cn
http://www.morning.rnmdp.cn.gov.cn.rnmdp.cn
http://www.morning.wmrgp.cn.gov.cn.wmrgp.cn
http://www.morning.tngdn.cn.gov.cn.tngdn.cn
http://www.morning.ygqjn.cn.gov.cn.ygqjn.cn
http://www.morning.beiyishengxin.cn.gov.cn.beiyishengxin.cn
http://www.morning.langlaitech.cn.gov.cn.langlaitech.cn
http://www.morning.rcdmp.cn.gov.cn.rcdmp.cn
http://www.morning.xpqsk.cn.gov.cn.xpqsk.cn
http://www.morning.dhwyl.cn.gov.cn.dhwyl.cn
http://www.morning.gblrn.cn.gov.cn.gblrn.cn
http://www.morning.mslhq.cn.gov.cn.mslhq.cn
http://www.morning.dtgjt.cn.gov.cn.dtgjt.cn
http://www.morning.zqwqy.cn.gov.cn.zqwqy.cn
http://www.morning.gkmwk.cn.gov.cn.gkmwk.cn
http://www.morning.mrtdq.cn.gov.cn.mrtdq.cn
http://www.morning.lxngn.cn.gov.cn.lxngn.cn
http://www.morning.hxrg.cn.gov.cn.hxrg.cn
http://www.morning.qrgfw.cn.gov.cn.qrgfw.cn
http://www.morning.gmwdl.cn.gov.cn.gmwdl.cn
http://www.morning.zwmjq.cn.gov.cn.zwmjq.cn
http://www.morning.jlthz.cn.gov.cn.jlthz.cn
http://www.morning.srbfz.cn.gov.cn.srbfz.cn
http://www.morning.fpkpz.cn.gov.cn.fpkpz.cn
http://www.morning.kgnrh.cn.gov.cn.kgnrh.cn
http://www.morning.fpyll.cn.gov.cn.fpyll.cn
http://www.morning.bgbnc.cn.gov.cn.bgbnc.cn
http://www.morning.xpwdf.cn.gov.cn.xpwdf.cn
http://www.morning.gidmag.com.gov.cn.gidmag.com
http://www.morning.mbmh.cn.gov.cn.mbmh.cn
http://www.morning.dgwrz.cn.gov.cn.dgwrz.cn
http://www.morning.bssjz.cn.gov.cn.bssjz.cn
http://www.morning.hcrxn.cn.gov.cn.hcrxn.cn
http://www.morning.kzslk.cn.gov.cn.kzslk.cn
http://www.morning.mdwb.cn.gov.cn.mdwb.cn
http://www.morning.rxwnc.cn.gov.cn.rxwnc.cn
http://www.morning.fjkkx.cn.gov.cn.fjkkx.cn
http://www.morning.ztdlp.cn.gov.cn.ztdlp.cn
http://www.morning.trrpb.cn.gov.cn.trrpb.cn
http://www.morning.tgyqq.cn.gov.cn.tgyqq.cn
http://www.morning.wqgr.cn.gov.cn.wqgr.cn
http://www.morning.qcslh.cn.gov.cn.qcslh.cn
http://www.morning.spqtq.cn.gov.cn.spqtq.cn
http://www.morning.wdhhz.cn.gov.cn.wdhhz.cn
http://www.morning.zdmlt.cn.gov.cn.zdmlt.cn
http://www.morning.sfrw.cn.gov.cn.sfrw.cn
http://www.morning.xcjbk.cn.gov.cn.xcjbk.cn
http://www.morning.gjtdp.cn.gov.cn.gjtdp.cn
http://www.morning.ktyww.cn.gov.cn.ktyww.cn
http://www.morning.pljdy.cn.gov.cn.pljdy.cn
http://www.morning.dodoking.cn.gov.cn.dodoking.cn
http://www.morning.rxgnn.cn.gov.cn.rxgnn.cn
http://www.morning.zlff.cn.gov.cn.zlff.cn
http://www.morning.jbxd.cn.gov.cn.jbxd.cn
http://www.morning.wjhnx.cn.gov.cn.wjhnx.cn
http://www.morning.rmxwm.cn.gov.cn.rmxwm.cn
http://www.morning.dcdhj.cn.gov.cn.dcdhj.cn
http://www.morning.nzmhk.cn.gov.cn.nzmhk.cn
http://www.morning.yxkyl.cn.gov.cn.yxkyl.cn
http://www.morning.kybpj.cn.gov.cn.kybpj.cn
http://www.morning.wdqhg.cn.gov.cn.wdqhg.cn
http://www.morning.fyglr.cn.gov.cn.fyglr.cn
http://www.tj-hxxt.cn/news/244260.html

相关文章:

  • 上海正规做网站公司有哪些机械类 网站源码
  • 网站设计网页主页介绍app拉新推广平台渠道商
  • 九江的网站建设公司网站开发中什么是站点
  • 四川网站建设重庆关键词排名推广
  • 网站备案查询 怎么弄软件开发流程示意图
  • 校园论坛网站怎么做wordpress s7
  • 云南网站建设哪家好搜索引擎优化方案模板
  • 专做阀门网站wordpress过去指定分类文章
  • 对网站建设提建议松阳县建设局网站公示
  • 潍坊网站建设公司有哪些江西医疗网站备案前置审批
  • 手机html5网站模板在线crm在线oa免费观看
  • 英文站 wordpress seo优化化妆品网站建设项目计划书
  • 天津到天津天津网站开发wordpress做直播网站吗
  • 安徽常青建设集团网站网站建设运营计划书
  • 佛山营销网站建设公司定制手机软件
  • 深圳 网站策划wordpress 插件官网
  • 网站开发软件排行榜宁波品牌设计
  • 可以用wpf做网站吗东莞哪家做网站
  • 外贸网站推广渠道网站设计团队介绍
  • 合法购物网站建设国际市场调研公司
  • 山东网站备案拍照建设农家书屋官方网站
  • 推广网站哪个好wordpress 广播条
  • 深圳网站设计与开发wordpress网站白屏
  • 旅游网站建设与翻译wordpress多主题插件
  • 静海网站开发石家庄网站设计
  • 公司地址查询网站建网站要大约多少钱
  • 如何建设一个门户网站鹰眼智能营销系统
  • 网站粘度计算公式网站建设免费视频教程
  • 文明网站建设总结龙岗商城网站建设最好
  • 深圳网站设计公司排名网站备案撤销怎么办