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

江苏省交通建设厅门户网站/天天seo伪原创工具

江苏省交通建设厅门户网站,天天seo伪原创工具,如何在ftp做网站,网站运营管理办法在之前的博客中 【JavaEE进阶】Spring AOP使用篇_aop多个切点-CSDN博客 我们主要学习了SpringAOP的应用, 接下来我们来学习SpringAOP的原理, 也就是Spring是如何实现AOP的. SpringAOP 是基于动态代理来实现AOP的,咱们学习内容主要分以下两部分 1.代理模式 2.Spring AOP源码剖…

在之前的博客中 【JavaEE进阶】Spring AOP使用篇_aop多个切点-CSDN博客

我们主要学习了SpringAOP的应用, 接下来我们来学习SpringAOP的原理, 也就是Spring是如何实现AOP的.

SpringAOP 是基于动态代理来实现AOP的,咱们学习内容主要分以下两部分
1.代理模式
2.Spring AOP源码剖析

1.代理模式

定义: 为其他对象提供一种代理以控制对这个对象的访问, 它的作用就是通过提供一个代理类, 让我们在调用目标方法的时候, 不再是直接对目标方法进行调用, 而是通过代理类间接调用.

在某些情况下, 一个对象不适合或者不能直接引用另一个对象, 而代理对象可以在客户端和目标对象之间起到中介的作用.

使用代理前:

使用代码后:

比如房屋租赁:

Subject: 就是提前定义了房东做的事情,交给中介代理,也是中介要做的事情
RealSubiect: 房东
Proxy: 中介

UML 类图如下:

代理模式可以在不修改被代理对象的基础上, 通过扩展代理类, 进行一些功能的附加与增强
根据代理的创建时期, 代理模式分为静态代理动态代理:

静态代理: 由程序员创建代理类或特定工具自动生成源代码再对其编译,在程序运行前代理类的
class 文件就已经存在了

动态代理: 在程序运行时,运用反射机制动态创建而成

静态代理:  由程序员创建代理类或特定工具自动生成源代码再对其编译, 在程序运行前代理类的.class 文件就已经存在了
动态代理:  在程序运行时, 运用反射机制动态创建而成

以房东和中介的的关系举例:

1.1 静态代理

以房东和中介的例子模拟静态代理:

1.定义接口(定义房东要做的事情,也是中介需要做的事情)

package com.example.aop.proxy;/*** 业务接口类*/
public interface HouseSubject {void rentHouse();void saleHouse();
}

 2.实现接口(房东出租房子)目标对象:

package com.example.aop.proxy;/*** 业务实现类*/
public class RealHouseSubject implements HouseSubject {@Overridepublic void rentHouse() {System.out.println("我是房东, 我出租房子");}@Overridepublic void saleHouse() {System.out.println("我是房东, 我出售房子");}
}

3.代理(中介,帮房东出租房子)

package com.example.aop.proxy;/*** 静态代理的代理类 (中介)*/public class HouseProxy implements HouseSubject {//房东对象private HouseSubject target;public HouseProxy(HouseSubject target) {this.target = target;}@Overridepublic void rentHouse() {//代理前System.out.println("我是中介, 开始代理");//出租房子target.rentHouse();//出租后System.out.println("我是中介, 结束代理");}@Overridepublic void saleHouse() {//代理前System.out.println("我是中介, 开始代理");//出售房子target.saleHouse();//出租后System.out.println("我是中介, 结束代理");}
}

 测试:

package com.example.aop.proxy;public class Main {public static void main(String[] args) {
//        静态代理HouseProxy proxy = new HouseProxy(new RealHouseSubject());proxy.rentHouse();proxy.saleHouse();System.out.println("========================");HouseSubject houseSubject = new RealHouseSubject();houseSubject.rentHouse();houseSubject.saleHouse();}
}

上面这个代理实现方式就是静态代理(仿佛啥也没干).

从上述程序可以看出, 虽然静态代理也完成了对目标对象的代理, 但是由于代码都写死了, 对目标对象的每个方法的增强都是手动完成的,非常不灵活. 所以日常开发几乎看不到静态代理的场景. 

我们修改接口(Subject)和业务实现类(RealSubject)时, 还需要修改代理类(Proxy).

同样的, 如果有新增接口(Subiect)和业务实现类(RealSubiect), 也需要对每一个业务实现类新增代理类(Proxy). 既然代理的流程是一样的, 有没有一种办法, 让他们通过一个代理类来实现呢?

这就需要用到动态代理技术了 

1.2 动态代理

相比于静态代理来说,动态代理更加灵活.
我们不需要针对每个目标对象都单独创建一个代理对象, 而是把这个创建代理对象的工作推迟到程序运行时由JVM来实现, 也就是说动态代理在程序运行时, 根据需要动态创建生成

比如房屋中介,我不需要提前预测都有哪些业务, 而是业务来了我再根据情况创建

我们还是先看代码再来理解,Java也对动态代理进行了实现, 并给我们提供了一些AP1, 常见的实现方式有两种:


动态代理在我们日常开发中使用的相对较少,但是在框架中几乎是必用的一门技术, 学会了动态代理之后, 对于我们理解和学习各种框架的原理也非常有帮助.

JDK动态代理 

JDK动态代理实现步骤:

定义JDK动态代理类

实现 InvocationHandler 接口

package com.example.aop.proxy;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;public class JDKInvocationHandler implements InvocationHandler   {private Object target; //目标对象public JDKInvocationHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("我是代理, 开始代理");//通过反射, 调用目标对象的方法Object result = method.invoke(target, args);System.out.println("我是代理, 结束代理");return result;}
}

创建一个代理对象并使用:


import java.lang.reflect.Proxy;public class Main {public static void main(String[] args) {//JDK动态代理/***     public static Object newProxyInstance(ClassLoader loader,*                                           Class<?>[] interfaces,*                                           InvocationHandler h) {*     loader: 加载我们代理类的classload*     interfaces: 要实现的接口*     h: 代理要做的事情, 需要实现 InvocationHandler 这个接口*///目标对象RealHouseSubject target = new RealHouseSubject();//动态生成代理对象HouseSubject proxy = (HouseSubject) Proxy.newProxyInstance(target.getClass().getClassLoader(),new Class[] {HouseSubject.class},new JDKInvocationHandler(target));proxy.rentHouse();proxy.saleHouse();}
}

JDK动态代理只能代理接口, 不能代理类:

运行成功

 运行失败

CGLIB动态代理

JDK 动态代理有一个最致命的问题是其只能代理实现了接口的类
有些场景下,我们的业务代码是直接实现的,并没有接口定义,为了解决这个问题,我们可以用 CGLIB 动态代理机制来解决.

CGLIB(Code Generation Library)是一个基于ASM的字节码生成库,它允许我们在运行时对字节码进行修改和动态生成.  CGLIB 通过继承方式实现代理,很多知名的开源框架都使用到了CGLIB.

例如 Spring中的 AOP 模块中: 如果目标对象实现了接口,则默认采用 JDK动态代理, 否则采用 CGLIB 动态代理.

CGLIB 动态代理类实现步骤

 添加依赖

和JDK动态代理不同, CGLlB(Code Generation Library) 实际是属于一个开源项目,如果你要使用它的话,需要手动添加相关依赖

<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.3.0</version>
</dependency>

自定义 MethodInterceptor(方法拦截器)
实现MethodInterceptor接

package com.example.aop.proxy;import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;import java.lang.reflect.Method;public class CGLibMethodInterceptor implements MethodInterceptor {private Object target;public CGLibMethodInterceptor(Object target) {this.target = target;}/*** 调用代理对象*/@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("我是中介, 开始代理");Object result = method.invoke(target, args);System.out.println("我是中介, 结束代理");return result;}
}

创建代理类,并使用

package com.example.aop.proxy;import org.springframework.cglib.proxy.Enhancer;public class Main {public static void main(String[] args) {//使用CGLib完成代理//代理接口, 运行成功HouseSubject target = new RealHouseSubject();HouseSubject houseSubject = (HouseSubject) Enhancer.create(target.getClass(), new CGLibMethodInterceptor(target));houseSubject.saleHouse();houseSubject.rentHouse();System.out.println("====================");//代理类, 运行成功RealHouseSubject realHouseSubject =  (RealHouseSubject) Enhancer.create(target.getClass(), new CGLibMethodInterceptor(target));realHouseSubject.saleHouse();realHouseSubject.rentHouse();}
}

CGLIB既可以代理接口, 又可以代理类: 

代码简单讲解
1. Methodinterceptor

MethodInterceptor 和 JDK动态代理中的 InvocationHandler 类似,它只定义了一个方法 intercept(),用于增强目标方法,

public interface MethodInterceptor extends Callback {/*** 参数说明: * o: 被代理的对象 * method: ⽬标⽅法(被拦截的⽅法, 也就是需要增强的⽅法) * objects: ⽅法⼊参 * methodProxy: ⽤于调⽤原始⽅法 */Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable;
}

2. Enhancer.create()
Enhancer.create()用来生成一个代理对象

public static Object create(Class type, Callback callback) {//...代码省略 
}

参数说明:

type: 被代理类的类型(类或接口)
callback: 自定义方法拦截器 MethodInterceptor

JDK动态代理和CGLIB动态代理的区别

JDK 可以代理接口, 不可以代理类

CGLib 既可以代理接口, 又可以代理类

JDK 动态代理是 Java 标准库的一部分,不需要额外的依赖。只要使用的是 Java 开发环境,就可以直接使用 JDK 动态代理

CGLIB 是一个第三方库,需要在项目中添加相应的依赖才能使用。

2. SpringAOP 源码阅读

SpringAOP 主要基于两种方式实现的: JDK及 CGLIB 的方式

生成代理对象的逻辑在父类 AbstractAutoProxyCreator 中
Spring 对于 AOP 的实现,基本上都是靠  AnnotationAwareAspectJAutoProxyCreator 去完成


/*** {@link org.springframework.beans.factory.config.BeanPostProcessor} implementation* that wraps each eligible bean with an AOP proxy, delegating to specified interceptors* before invoking the bean itself.** <p>This class distinguishes between "common" interceptors: shared for all proxies it* creates, and "specific" interceptors: unique per bean instance. There need not be any* common interceptors. If there are, they are set using the interceptorNames property.* As with {@link org.springframework.aop.framework.ProxyFactoryBean}, interceptors names* in the current factory are used rather than bean references to allow correct handling* of prototype advisors and interceptors: for example, to support stateful mixins.* Any advice type is supported for {@link #setInterceptorNames "interceptorNames"} entries.** <p>Such auto-proxying is particularly useful if there's a large number of beans that* need to be wrapped with similar proxies, i.e. delegating to the same interceptors.* Instead of x repetitive proxy definitions for x target beans, you can register* one single such post processor with the bean factory to achieve the same effect.** <p>Subclasses can apply any strategy to decide if a bean is to be proxied, e.g. by type,* by name, by definition details, etc. They can also return additional interceptors that* should just be applied to the specific bean instance. A simple concrete implementation is* {@link BeanNameAutoProxyCreator}, identifying the beans to be proxied via given names.** <p>Any number of {@link TargetSourceCreator} implementations can be used to create* a custom target source: for example, to pool prototype objects. Auto-proxying will* occur even if there is no advice, as long as a TargetSourceCreator specifies a custom* {@link org.springframework.aop.TargetSource}. If there are no TargetSourceCreators set,* or if none matches, a {@link org.springframework.aop.target.SingletonTargetSource}* will be used by default to wrap the target bean instance.** @author Juergen Hoeller* @author Rod Johnson* @author Rob Harrop* @author Sam Brannen* @since 13.10.2003* @see #setInterceptorNames* @see #getAdvicesAndAdvisorsForBean* @see BeanNameAutoProxyCreator* @see DefaultAdvisorAutoProxyCreator*/
@SuppressWarnings("serial")
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupportimplements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {/*** Convenience constant for subclasses: Return value for "do not proxy".* @see #getAdvicesAndAdvisorsForBean*/@Nullableprotected static final Object[] DO_NOT_PROXY = null;/*** Convenience constant for subclasses: Return value for* "proxy without additional interceptors, just the common ones".* @see #getAdvicesAndAdvisorsForBean*/protected static final Object[] PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS = new Object[0];/** Logger available to subclasses. */protected final Log logger = LogFactory.getLog(getClass());/** Default is global AdvisorAdapterRegistry. */private AdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.getInstance();/*** Indicates whether the proxy should be frozen. Overridden from super* to prevent the configuration from becoming frozen too early.*/private boolean freezeProxy = false;/** Default is no common interceptors. */private String[] interceptorNames = new String[0];private boolean applyCommonInterceptorsFirst = true;@Nullableprivate TargetSourceCreator[] customTargetSourceCreators;@Nullableprivate BeanFactory beanFactory;private final Set<String> targetSourcedBeans = Collections.newSetFromMap(new ConcurrentHashMap<>(16));private final Map<Object, Object> earlyBeanReferences = new ConcurrentHashMap<>(16);private final Map<Object, Class<?>> proxyTypes = new ConcurrentHashMap<>(16);private final Map<Object, Boolean> advisedBeans = new ConcurrentHashMap<>(256);/*** Set whether the proxy should be frozen, preventing advice* from being added to it once it is created.* <p>Overridden from the superclass to prevent the proxy configuration* from being frozen before the proxy is created.*/@Overridepublic void setFrozen(boolean frozen) {this.freezeProxy = frozen;}@Overridepublic boolean isFrozen() {return this.freezeProxy;}/*** Specify the {@link AdvisorAdapterRegistry} to use.* <p>Default is the global {@link AdvisorAdapterRegistry}.* @see org.springframework.aop.framework.adapter.GlobalAdvisorAdapterRegistry*/public void setAdvisorAdapterRegistry(AdvisorAdapterRegistry advisorAdapterRegistry) {this.advisorAdapterRegistry = advisorAdapterRegistry;}/*** Set custom {@code TargetSourceCreators} to be applied in this order.* If the list is empty, or they all return null, a {@link SingletonTargetSource}* will be created for each bean.* <p>Note that TargetSourceCreators will kick in even for target beans* where no advices or advisors have been found. If a {@code TargetSourceCreator}* returns a {@link TargetSource} for a specific bean, that bean will be proxied* in any case.* <p>{@code TargetSourceCreators} can only be invoked if this post processor is used* in a {@link BeanFactory} and its {@link BeanFactoryAware} callback is triggered.* @param targetSourceCreators the list of {@code TargetSourceCreators}.* Ordering is significant: The {@code TargetSource} returned from the first matching* {@code TargetSourceCreator} (that is, the first that returns non-null) will be used.*/public void setCustomTargetSourceCreators(TargetSourceCreator... targetSourceCreators) {this.customTargetSourceCreators = targetSourceCreators;}/*** Set the common interceptors. These must be bean names in the current factory.* They can be of any advice or advisor type Spring supports.* <p>If this property isn't set, there will be zero common interceptors.* This is perfectly valid, if "specific" interceptors such as matching* Advisors are all we want.*/public void setInterceptorNames(String... interceptorNames) {this.interceptorNames = interceptorNames;}/*** Set whether the common interceptors should be applied before bean-specific ones.* Default is "true"; else, bean-specific interceptors will get applied first.*/public void setApplyCommonInterceptorsFirst(boolean applyCommonInterceptorsFirst) {this.applyCommonInterceptorsFirst = applyCommonInterceptorsFirst;}@Overridepublic void setBeanFactory(BeanFactory beanFactory) {this.beanFactory = beanFactory;}/*** Return the owning {@link BeanFactory}.* May be {@code null}, as this post-processor doesn't need to belong to a bean factory.*/@Nullableprotected BeanFactory getBeanFactory() {return this.beanFactory;}@Override@Nullablepublic Class<?> predictBeanType(Class<?> beanClass, String beanName) {if (this.proxyTypes.isEmpty()) {return null;}Object cacheKey = getCacheKey(beanClass, beanName);return this.proxyTypes.get(cacheKey);}@Overridepublic Class<?> determineBeanType(Class<?> beanClass, String beanName) {Object cacheKey = getCacheKey(beanClass, beanName);Class<?> proxyType = this.proxyTypes.get(cacheKey);if (proxyType == null) {TargetSource targetSource = getCustomTargetSource(beanClass, beanName);if (targetSource != null) {if (StringUtils.hasLength(beanName)) {this.targetSourcedBeans.add(beanName);}}else {targetSource = EmptyTargetSource.forClass(beanClass);}Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);if (specificInterceptors != DO_NOT_PROXY) {this.advisedBeans.put(cacheKey, Boolean.TRUE);proxyType = createProxyClass(beanClass, beanName, specificInterceptors, targetSource);this.proxyTypes.put(cacheKey, proxyType);}}return (proxyType != null ? proxyType : beanClass);}@Override@Nullablepublic Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) {return null;}@Overridepublic Object getEarlyBeanReference(Object bean, String beanName) {Object cacheKey = getCacheKey(bean.getClass(), beanName);this.earlyBeanReferences.put(cacheKey, bean);return wrapIfNecessary(bean, beanName, cacheKey);}@Override@Nullablepublic Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {Object cacheKey = getCacheKey(beanClass, beanName);if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {if (this.advisedBeans.containsKey(cacheKey)) {return null;}if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {this.advisedBeans.put(cacheKey, Boolean.FALSE);return null;}}// Create proxy here if we have a custom TargetSource.// Suppresses unnecessary default instantiation of the target bean:// The TargetSource will handle target instances in a custom fashion.TargetSource targetSource = getCustomTargetSource(beanClass, beanName);if (targetSource != null) {if (StringUtils.hasLength(beanName)) {this.targetSourcedBeans.add(beanName);}Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);this.proxyTypes.put(cacheKey, proxy.getClass());return proxy;}return null;}@Overridepublic PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {return pvs;  // skip postProcessPropertyValues}/*** Create a proxy with the configured interceptors if the bean is* identified as one to proxy by the subclass.* @see #getAdvicesAndAdvisorsForBean*/@Override@Nullablepublic Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {if (bean != null) {Object cacheKey = getCacheKey(bean.getClass(), beanName);if (this.earlyBeanReferences.remove(cacheKey) != bean) {return wrapIfNecessary(bean, beanName, cacheKey);}}return bean;}/*** Build a cache key for the given bean class and bean name.* <p>Note: As of 4.2.3, this implementation does not return a concatenated* class/name String anymore but rather the most efficient cache key possible:* a plain bean name, prepended with {@link BeanFactory#FACTORY_BEAN_PREFIX}* in case of a {@code FactoryBean}; or if no bean name specified, then the* given bean {@code Class} as-is.* @param beanClass the bean class* @param beanName the bean name* @return the cache key for the given class and name*/protected Object getCacheKey(Class<?> beanClass, @Nullable String beanName) {if (StringUtils.hasLength(beanName)) {return (FactoryBean.class.isAssignableFrom(beanClass) ?BeanFactory.FACTORY_BEAN_PREFIX + beanName : beanName);}else {return beanClass;}}/*** Wrap the given bean if necessary, i.e. if it is eligible for being proxied.* @param bean the raw bean instance* @param beanName the name of the bean* @param cacheKey the cache key for metadata access* @return a proxy wrapping the bean, or the raw bean instance as-is*/protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {return bean;}if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {return bean;}if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean;}// Create proxy if we have advice.Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);if (specificInterceptors != DO_NOT_PROXY) {this.advisedBeans.put(cacheKey, Boolean.TRUE);Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));this.proxyTypes.put(cacheKey, proxy.getClass());return proxy;}this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean;}/*** Return whether the given bean class represents an infrastructure class* that should never be proxied.* <p>The default implementation considers Advices, Advisors and* AopInfrastructureBeans as infrastructure classes.* @param beanClass the class of the bean* @return whether the bean represents an infrastructure class* @see org.aopalliance.aop.Advice* @see org.springframework.aop.Advisor* @see org.springframework.aop.framework.AopInfrastructureBean* @see #shouldSkip*/protected boolean isInfrastructureClass(Class<?> beanClass) {boolean retVal = Advice.class.isAssignableFrom(beanClass) ||Pointcut.class.isAssignableFrom(beanClass) ||Advisor.class.isAssignableFrom(beanClass) ||AopInfrastructureBean.class.isAssignableFrom(beanClass);if (retVal && logger.isTraceEnabled()) {logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]");}return retVal;}/*** Subclasses should override this method to return {@code true} if the* given bean should not be considered for auto-proxying by this post-processor.* <p>Sometimes we need to be able to avoid this happening, e.g. if it will lead to* a circular reference or if the existing target instance needs to be preserved.* This implementation returns {@code false} unless the bean name indicates an* "original instance" according to {@code AutowireCapableBeanFactory} conventions.* @param beanClass the class of the bean* @param beanName the name of the bean* @return whether to skip the given bean* @see org.springframework.beans.factory.config.AutowireCapableBeanFactory#ORIGINAL_INSTANCE_SUFFIX*/protected boolean shouldSkip(Class<?> beanClass, String beanName) {return AutoProxyUtils.isOriginalInstance(beanName, beanClass);}/*** Create a target source for bean instances. Uses any TargetSourceCreators if set.* Returns {@code null} if no custom TargetSource should be used.* <p>This implementation uses the "customTargetSourceCreators" property.* Subclasses can override this method to use a different mechanism.* @param beanClass the class of the bean to create a TargetSource for* @param beanName the name of the bean* @return a TargetSource for this bean* @see #setCustomTargetSourceCreators*/@Nullableprotected TargetSource getCustomTargetSource(Class<?> beanClass, String beanName) {// We can't create fancy target sources for directly registered singletons.if (this.customTargetSourceCreators != null &&this.beanFactory != null && this.beanFactory.containsBean(beanName)) {for (TargetSourceCreator tsc : this.customTargetSourceCreators) {TargetSource ts = tsc.getTargetSource(beanClass, beanName);if (ts != null) {// Found a matching TargetSource.if (logger.isTraceEnabled()) {logger.trace("TargetSourceCreator [" + tsc +"] found custom TargetSource for bean with name '" + beanName + "'");}return ts;}}}// No custom TargetSource found.return null;}/*** Create an AOP proxy for the given bean.* @param beanClass the class of the bean* @param beanName the name of the bean* @param specificInterceptors the set of interceptors that is* specific to this bean (may be empty, but not null)* @param targetSource the TargetSource for the proxy,* already pre-configured to access the bean* @return the AOP proxy for the bean* @see #buildAdvisors*/protected Object createProxy(Class<?> beanClass, @Nullable String beanName,@Nullable Object[] specificInterceptors, TargetSource targetSource) {return buildProxy(beanClass, beanName, specificInterceptors, targetSource, false);}private Class<?> createProxyClass(Class<?> beanClass, @Nullable String beanName,@Nullable Object[] specificInterceptors, TargetSource targetSource) {return (Class<?>) buildProxy(beanClass, beanName, specificInterceptors, targetSource, true);}private Object buildProxy(Class<?> beanClass, @Nullable String beanName,@Nullable Object[] specificInterceptors, TargetSource targetSource, boolean classOnly) {if (this.beanFactory instanceof ConfigurableListableBeanFactory clbf) {AutoProxyUtils.exposeTargetClass(clbf, beanName, beanClass);}ProxyFactory proxyFactory = new ProxyFactory();proxyFactory.copyFrom(this);if (proxyFactory.isProxyTargetClass()) {// Explicit handling of JDK proxy targets and lambdas (for introduction advice scenarios)if (Proxy.isProxyClass(beanClass) || ClassUtils.isLambdaClass(beanClass)) {// Must allow for introductions; can't just set interfaces to the proxy's interfaces only.for (Class<?> ifc : beanClass.getInterfaces()) {proxyFactory.addInterface(ifc);}}}else {// No proxyTargetClass flag enforced, let's apply our default checks...if (shouldProxyTargetClass(beanClass, beanName)) {proxyFactory.setProxyTargetClass(true);}else {evaluateProxyInterfaces(beanClass, proxyFactory);}}Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);proxyFactory.addAdvisors(advisors);proxyFactory.setTargetSource(targetSource);customizeProxyFactory(proxyFactory);proxyFactory.setFrozen(this.freezeProxy);if (advisorsPreFiltered()) {proxyFactory.setPreFiltered(true);}// Use original ClassLoader if bean class not locally loaded in overriding class loaderClassLoader classLoader = getProxyClassLoader();if (classLoader instanceof SmartClassLoader smartClassLoader && classLoader != beanClass.getClassLoader()) {classLoader = smartClassLoader.getOriginalClassLoader();}return (classOnly ? proxyFactory.getProxyClass(classLoader) : proxyFactory.getProxy(classLoader));}/*** Determine whether the given bean should be proxied with its target class rather than its interfaces.* <p>Checks the {@link AutoProxyUtils#PRESERVE_TARGET_CLASS_ATTRIBUTE "preserveTargetClass" attribute}* of the corresponding bean definition.* @param beanClass the class of the bean* @param beanName the name of the bean* @return whether the given bean should be proxied with its target class* @see AutoProxyUtils#shouldProxyTargetClass*/protected boolean shouldProxyTargetClass(Class<?> beanClass, @Nullable String beanName) {return (this.beanFactory instanceof ConfigurableListableBeanFactory clbf &&AutoProxyUtils.shouldProxyTargetClass(clbf, beanName));}/*** Return whether the Advisors returned by the subclass are pre-filtered* to match the bean's target class already, allowing the ClassFilter check* to be skipped when building advisors chains for AOP invocations.* <p>Default is {@code false}. Subclasses may override this if they* will always return pre-filtered Advisors.* @return whether the Advisors are pre-filtered* @see #getAdvicesAndAdvisorsForBean* @see org.springframework.aop.framework.Advised#setPreFiltered*/protected boolean advisorsPreFiltered() {return false;}/*** Determine the advisors for the given bean, including the specific interceptors* as well as the common interceptor, all adapted to the Advisor interface.* @param beanName the name of the bean* @param specificInterceptors the set of interceptors that is* specific to this bean (may be empty, but not null)* @return the list of Advisors for the given bean*/protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {// Handle prototypes correctly...Advisor[] commonInterceptors = resolveInterceptorNames();List<Object> allInterceptors = new ArrayList<>();if (specificInterceptors != null) {if (specificInterceptors.length > 0) {// specificInterceptors may equal PROXY_WITHOUT_ADDITIONAL_INTERCEPTORSallInterceptors.addAll(Arrays.asList(specificInterceptors));}if (commonInterceptors.length > 0) {if (this.applyCommonInterceptorsFirst) {allInterceptors.addAll(0, Arrays.asList(commonInterceptors));}else {allInterceptors.addAll(Arrays.asList(commonInterceptors));}}}if (logger.isTraceEnabled()) {int nrOfCommonInterceptors = commonInterceptors.length;int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);logger.trace("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +" common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");}Advisor[] advisors = new Advisor[allInterceptors.size()];for (int i = 0; i < allInterceptors.size(); i++) {advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));}return advisors;}/*** Resolves the specified interceptor names to Advisor objects.* @see #setInterceptorNames*/private Advisor[] resolveInterceptorNames() {BeanFactory bf = this.beanFactory;ConfigurableBeanFactory cbf = (bf instanceof ConfigurableBeanFactory _cbf ? _cbf : null);List<Advisor> advisors = new ArrayList<>();for (String beanName : this.interceptorNames) {if (cbf == null || !cbf.isCurrentlyInCreation(beanName)) {Assert.state(bf != null, "BeanFactory required for resolving interceptor names");Object next = bf.getBean(beanName);advisors.add(this.advisorAdapterRegistry.wrap(next));}}return advisors.toArray(new Advisor[0]);}/*** Subclasses may choose to implement this: for example,* to change the interfaces exposed.* <p>The default implementation is empty.* @param proxyFactory a ProxyFactory that is already configured with* TargetSource and interfaces and will be used to create the proxy* immediately after this method returns*/protected void customizeProxyFactory(ProxyFactory proxyFactory) {}/*** Return whether the given bean is to be proxied, what additional* advices (e.g. AOP Alliance interceptors) and advisors to apply.* @param beanClass the class of the bean to advise* @param beanName the name of the bean* @param customTargetSource the TargetSource returned by the* {@link #getCustomTargetSource} method: may be ignored.* Will be {@code null} if no custom target source is in use.* @return an array of additional interceptors for the particular bean;* or an empty array if no additional interceptors but just the common ones;* or {@code null} if no proxy at all, not even with the common interceptors.* See constants DO_NOT_PROXY and PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS.* @throws BeansException in case of errors* @see #DO_NOT_PROXY* @see #PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS*/@Nullableprotected abstract Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName,@Nullable TargetSource customTargetSource) throws BeansException;}

代理工厂有一个重要的属性: proxyTargetClass,默认值为false.也可以通过程序设置

Spring Boot 2.X开始,默认使用CGLIB代理

可以通过配置项 spring.aop.proxy-target-class=false 来进行修改, 设置默认为jdk代理
SpringBoot设置 @EnableAspectJAutoProxy 无效, 因为Spring Boot 默认使用
AopAutoConfiguration 进行装配

我看点进去看代理⼯⼚的代码


/*** Factory for AOP proxies for programmatic use, rather than via declarative* setup in a bean factory. This class provides a simple way of obtaining* and configuring AOP proxy instances in custom user code.** @author Rod Johnson* @author Juergen Hoeller* @author Rob Harrop* @since 14.03.2003*/
@SuppressWarnings("serial")
public class ProxyFactory extends ProxyCreatorSupport {/*** Create a new ProxyFactory.*/public ProxyFactory() {}/*** Create a new ProxyFactory.* <p>Will proxy all interfaces that the given target implements.* @param target the target object to be proxied*/public ProxyFactory(Object target) {setTarget(target);setInterfaces(ClassUtils.getAllInterfaces(target));}/*** Create a new ProxyFactory.* <p>No target, only interfaces. Must add interceptors.* @param proxyInterfaces the interfaces that the proxy should implement*/public ProxyFactory(Class<?>... proxyInterfaces) {setInterfaces(proxyInterfaces);}/*** Create a new ProxyFactory for the given interface and interceptor.* <p>Convenience method for creating a proxy for a single interceptor,* assuming that the interceptor handles all calls itself rather than* delegating to a target, like in the case of remoting proxies.* @param proxyInterface the interface that the proxy should implement* @param interceptor the interceptor that the proxy should invoke*/public ProxyFactory(Class<?> proxyInterface, Interceptor interceptor) {addInterface(proxyInterface);addAdvice(interceptor);}/*** Create a ProxyFactory for the specified {@code TargetSource},* making the proxy implement the specified interface.* @param proxyInterface the interface that the proxy should implement* @param targetSource the TargetSource that the proxy should invoke*/public ProxyFactory(Class<?> proxyInterface, TargetSource targetSource) {addInterface(proxyInterface);setTargetSource(targetSource);}/*** Create a new proxy according to the settings in this factory.* <p>Can be called repeatedly. Effect will vary if we've added* or removed interfaces. Can add and remove interceptors.* <p>Uses a default class loader: Usually, the thread context class loader* (if necessary for proxy creation).* @return the proxy object*/public Object getProxy() {return createAopProxy().getProxy();}/*** Create a new proxy according to the settings in this factory.* <p>Can be called repeatedly. Effect will vary if we've added* or removed interfaces. Can add and remove interceptors.* <p>Uses the given class loader (if necessary for proxy creation).* @param classLoader the class loader to create the proxy with* (or {@code null} for the low-level proxy facility's default)* @return the proxy object*/public Object getProxy(@Nullable ClassLoader classLoader) {return createAopProxy().getProxy(classLoader);}/*** Determine the proxy class according to the settings in this factory.* @param classLoader the class loader to create the proxy class with* (or {@code null} for the low-level proxy facility's default)* @return the proxy class* @since 6.0*/public Class<?> getProxyClass(@Nullable ClassLoader classLoader) {return createAopProxy().getProxyClass(classLoader);}/*** Create a new proxy for the given interface and interceptor.* <p>Convenience method for creating a proxy for a single interceptor,* assuming that the interceptor handles all calls itself rather than* delegating to a target, like in the case of remoting proxies.* @param proxyInterface the interface that the proxy should implement* @param interceptor the interceptor that the proxy should invoke* @return the proxy object* @see #ProxyFactory(Class, org.aopalliance.intercept.Interceptor)*/@SuppressWarnings("unchecked")public static <T> T getProxy(Class<T> proxyInterface, Interceptor interceptor) {return (T) new ProxyFactory(proxyInterface, interceptor).getProxy();}/*** Create a proxy for the specified {@code TargetSource},* implementing the specified interface.* @param proxyInterface the interface that the proxy should implement* @param targetSource the TargetSource that the proxy should invoke* @return the proxy object* @see #ProxyFactory(Class, org.springframework.aop.TargetSource)*/@SuppressWarnings("unchecked")public static <T> T getProxy(Class<T> proxyInterface, TargetSource targetSource) {return (T) new ProxyFactory(proxyInterface, targetSource).getProxy();}/*** Create a proxy for the specified {@code TargetSource} that extends* the target class of the {@code TargetSource}.* @param targetSource the TargetSource that the proxy should invoke* @return the proxy object*/public static Object getProxy(TargetSource targetSource) {if (targetSource.getTargetClass() == null) {throw new IllegalArgumentException("Cannot create class proxy for TargetSource with null target class");}ProxyFactory proxyFactory = new ProxyFactory();proxyFactory.setTargetSource(targetSource);proxyFactory.setProxyTargetClass(true);return proxyFactory.getProxy();}}

createAopProxy的实现在 DefaultAopProxyFactory中


/*** Default {@link AopProxyFactory} implementation, creating either a CGLIB proxy* or a JDK dynamic proxy.** <p>Creates a CGLIB proxy if one the following is true for a given* {@link AdvisedSupport} instance:* <ul>* <li>the {@code optimize} flag is set* <li>the {@code proxyTargetClass} flag is set* <li>no proxy interfaces have been specified* </ul>** <p>In general, specify {@code proxyTargetClass} to enforce a CGLIB proxy,* or specify one or more interfaces to use a JDK dynamic proxy.** @author Rod Johnson* @author Juergen Hoeller* @author Sebastien Deleuze* @author Sam Brannen* @since 12.03.2004* @see AdvisedSupport#setOptimize* @see AdvisedSupport#setProxyTargetClass* @see AdvisedSupport#setInterfaces*/
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {/*** Singleton instance of this class.* @since 6.0.10*/public static final DefaultAopProxyFactory INSTANCE = new DefaultAopProxyFactory();private static final long serialVersionUID = 7930414337282325166L;@Overridepublic AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {if (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.");}if (targetClass.isInterface() || Proxy.isProxyClass(targetClass) || ClassUtils.isLambdaClass(targetClass)) {return new JdkDynamicAopProxy(config);}return new ObjenesisCglibAopProxy(config);}else {return new JdkDynamicAopProxy(config);}}/*** Determine whether the supplied {@link AdvisedSupport} has only the* {@link org.springframework.aop.SpringProxy} interface specified* (or no proxy interfaces specified at all).*/private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {Class<?>[] ifcs = config.getProxiedInterfaces();return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));}}

接下来就是创建代理了
JDK动态代理

CGLIB动态代理

CglibAopProxy类中:

@Overridepublic Object getProxy(@Nullable ClassLoader classLoader) {return buildProxy(classLoader, false);}@Overridepublic Class<?> getProxyClass(@Nullable ClassLoader classLoader) {return (Class<?>) buildProxy(classLoader, true);}private Object buildProxy(@Nullable ClassLoader classLoader, boolean classOnly) {if (logger.isTraceEnabled()) {logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());}try {Class<?> rootClass = this.advised.getTargetClass();Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");Class<?> proxySuperClass = rootClass;if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {proxySuperClass = rootClass.getSuperclass();Class<?>[] additionalInterfaces = rootClass.getInterfaces();for (Class<?> additionalInterface : additionalInterfaces) {this.advised.addInterface(additionalInterface);}}// Validate the class, writing log messages as necessary.validateClassIfNecessary(proxySuperClass, classLoader);// Configure CGLIB Enhancer...Enhancer enhancer = createEnhancer();if (classLoader != null) {enhancer.setClassLoader(classLoader);if (classLoader instanceof SmartClassLoader smartClassLoader &&smartClassLoader.isClassReloadable(proxySuperClass)) {enhancer.setUseCache(false);}}enhancer.setSuperclass(proxySuperClass);enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);enhancer.setAttemptLoad(true);enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));Callback[] callbacks = getCallbacks(rootClass);Class<?>[] types = new Class<?>[callbacks.length];for (int x = 0; x < types.length; x++) {types[x] = callbacks[x].getClass();}// fixedInterceptorMap only populated at this point, after getCallbacks call aboveProxyCallbackFilter filter = new ProxyCallbackFilter(this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset);enhancer.setCallbackFilter(filter);enhancer.setCallbackTypes(types);// Generate the proxy class and create a proxy instance.// ProxyCallbackFilter has method introspection capability with Advisor access.try {return (classOnly ? createProxyClass(enhancer) : createProxyClassAndInstance(enhancer, callbacks));}finally {// Reduce ProxyCallbackFilter to key-only state for its class cache role// in the CGLIB$CALLBACK_FILTER field, not leaking any Advisor state...filter.advised.reduceToAdvisorKey();}}catch (CodeGenerationException | IllegalArgumentException ex) {throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +": Common causes of this problem include using a final class or a non-visible class",ex);}catch (Throwable ex) {// TargetSource.getTarget() failedthrow new AopConfigException("Unexpected AOP exception", ex);}}

回顾:

1.什么是AOP

2.SpringAOP 的实现方式有哪些?

3.SpringAOP 的实现原理 (基于动态代理 1.JDK 2.CGLib)

4. Spring 使用的是那种代理方式?

Spring 默认 proxyTargetClass 值为false, 如果实现了接口, 使用JDK代理, 如果是普通类则使用CGLib代理

SpringBoot从2.x之后, proxyTargetClass值为true, 默认是使用CGLib代理

5. JDK动态代理和CGLib动态代理的区别?

总结 

相关文章:

【JavaEE进阶】Spring AOP 原理

在之前的博客中 【JavaEE进阶】Spring AOP使用篇_aop多个切点-CSDN博客 我们主要学习了SpringAOP的应用, 接下来我们来学习SpringAOP的原理, 也就是Spring是如何实现AOP的. SpringAOP 是基于动态代理来实现AOP的,咱们学习内容主要分以下两部分 1.代理模式 2.Spring AOP源码剖…...

【网络安全】2.3 安全的网络设计_2.防御深度原则

文章目录 一、网络架构二、网络设备三、网络策略四、处理网络安全事件五、实例学习&#xff1a;安全的网络设计结论 网络设计是网络安全的基础&#xff0c;一个好的网络设计可以有效的防止攻击者的入侵。在本篇文章中&#xff0c;我们将详细介绍如何设计一个安全的网络&#…...

测绘程序设计|C#字符串及其操作|分割|取子串|格式化数值|StringBuilder类

由于微信公众号改变了推送规则&#xff0c;为了每次新的推送可以在第一时间出现在您的订阅列表中&#xff0c;记得将本公众号设为星标或置顶喔~ 简单介绍了C#字符串分割、取子串、拼接、格式化数值以及StringBuilder类&#xff0c;拿捏测绘程序设计大赛~ &#x1f33f;前言 字…...

自然语言处理——Hugging Face 详解

Hugging Face 是一个以自然语言处理&#xff08;NLP&#xff09;为核心的人工智能平台和开源社区&#xff0c;提供了一系列非常流行的机器学习工具和预训练模型&#xff0c;尤其在文本生成、分类、翻译、情感分析等任务中表现出色。Hugging Face 旗下最为著名的项目是 Transfor…...

本地保存mysql凭据实现免密登录mysql

本地保存mysql凭据 mysql加密登录文件简介加密保存mysql用户的密码到本地凭据 mysql加密登录文件简介 要在 mysql客户端 上连接 MySQL 而无需在命令提示符上输入用户名和口令&#xff0c;下列三个位置可用于存储用户的mysql 凭证来满足此要求。 配置文件my.cnf或my.ini /etc…...

Ubuntu 22 安装 Apache Doris 3.0.3 笔记

Ubuntu 22 安装 Apache Doris 3.0.3 笔记 1. 环境准备 Doris 需要 Java 17 作为运行环境&#xff0c;所以首先需要安装 Java 17。 sudo apt-get install openjdk-17-jdk -y sudo update-alternatives --config java在安装 Java 17 后&#xff0c;可以通过 sudo update-alter…...

构建智能防线 灵途科技光电感知助力轨交全向安全防护

10月27日&#xff0c;在南京南站至紫金山东站间的高铁联络线上&#xff0c;一头野猪侵入轨道&#xff0c;与D5515次列车相撞&#xff0c;导致设备故障停车。 事故不仅造成南京南站部分列车晚点&#xff0c;还在故障排查过程中导致随车机械师因被邻线限速通过的列车碰撞而不幸身…...

【go从零单排】泛型(Generics)、链表

&#x1f308;Don’t worry , just coding! 内耗与overthinking只会削弱你的精力&#xff0c;虚度你的光阴&#xff0c;每天迈出一小步&#xff0c;回头时发现已经走了很远。 &#x1f4d7;概念 在Go语言中&#xff0c;泛型&#xff08;Generics&#xff09;允许你编写可以处理…...

IoTDB 与 HBase 对比详解:架构、功能与性能

五大方向&#xff0c;洞悉 IoTDB 与 HBase 的详尽对比&#xff01; 在物联网&#xff08;IoT&#xff09;领域&#xff0c;数据的采集、存储和分析是确保系统高效运行和决策准确的重要环节。随着物联网设备数量的增加和数据量的爆炸式增长&#xff0c;开发者和决策者们需要选择…...

推荐一款ETCD桌面客户端——Etcd Workbench

Etcd Workbench 我相信很多人在开始管理ETCD的时候都去搜了Etcd客户端工具&#xff0c;然后找到了官方的Etcd Manager&#xff0c;但用完之后发现它并不好用&#xff0c;还不支持多连接和代码格式化&#xff0c;并且已经好几年不更新了&#xff0c;于是市面上就有了好多其他客…...

01 Oracle 数据库存储结构深度解析:从数据文件到性能优化的全链路探究

文章目录 Oracle 数据库存储结构深度解析&#xff1a;从数据文件到性能优化的全链路探究一、Oracle存储结构的物理层次1.1 控制文件&#xff08;Control File&#xff09;1.2 联机重做日志文件&#xff08;Online Redo Log File&#xff09;1.3 数据文件&#xff08;Data File&…...

AI教育革命:个性化学习的新篇章

内容概要 在 教育 领域&#xff0c;人工智能 的崭露头角带来了前所未有的变化。如今&#xff0c;个性化学习 已不再是一个遥不可及的梦想&#xff0c;而是通过 AI 技术真正实现的可能。借助先进的数据分析能力&#xff0c;教师可以实时跟踪和评估每位学生的学习进度&#xff0…...

【网络原理】万字详解 UDP 和 TCP

&#x1f970;&#x1f970;&#x1f970;来都来了&#xff0c;不妨点个关注叭&#xff01; &#x1f449;博客主页&#xff1a;欢迎各位大佬!&#x1f448; 文章目录 1. UDP1.1 UDP 报文格式1.1.1 源端口/目的端口1.1.2 报文长度1.1.3 校验和 2. TCP2.1 TCP 报文结构2.2 TCP 特…...

从零开始搭建Halo个人博客

前言 老话说得好&#xff0c;好记性不如烂笔头。对于程序员来说&#xff0c;学无止境&#xff0c;需要学习的东西很多&#xff0c;而如果不记录下来可能过不了多久就忘记了&#xff0c;而记录下来这一步也能很好地贯彻费曼学习法。 其实网上有很多博客平台&#xff0c;但是自…...

AMD显卡低负载看视频掉驱动(chrome edge浏览器) 高负载玩游戏却稳定 解决方法——关闭MPO

2024.11.9更新 开关mpo ulps 感觉有用但是还是掉驱动&#xff0c;现在确定是window顶驱动问题 按网上的改注册表和组策略会让自己也打不上驱动 目前感觉最好的办法就是&#xff0c;重置此电脑&#xff0c;然后你就摆着电脑挂个十分钟半小时别动&#xff0c;一开始他是不显示…...

数据结构——二叉树(续集)

♥♥♥~~~~~~欢迎光临知星小度博客空间~~~~~~♥♥♥ ♥♥♥零星地变得优秀~也能拼凑出星河~♥♥♥ ♥♥♥我们一起努力成为更好的自己~♥♥♥ ♥♥♥如果这一篇博客对你有帮助~别忘了点赞分享哦~♥♥♥ ♥♥♥如果有什么问题可以评论区留言或者私信我哦~♥♥♥ ✨✨✨✨✨✨个人…...

ElasticSearch学习篇16_《检索技术核心20讲》进阶篇之空间检索

背景 学习极客实践课程《检索技术核心20讲》https://time.geekbang.org/column/article/215243&#xff0c;文档形式记录笔记。 相关问题&#xff1a; 查询范围固定的需求 直接计算两点之间距离区域二进制编码GeoHash编码 查询范围不固定的需求 GeoHash编码索引结构设计 基于…...

uni-app跨域set-cookie

set-cookie的值是作为一个权限控制的 首先&#xff0c;无论什么接口都会返回一个set-cookie&#xff0c;但未登录时&#xff0c;set-cookie是没有任何权限的 其次&#xff0c;登录接口请求时会修改set-cookie&#xff0c;并且在后续其他接口发起请求时&#xff0c;会在请求头…...

移动应用开发:简易登录页

文章目录 简介一&#xff0c;创建新活动二&#xff0c;设计UI布局三&#xff0c;编写活动代码四&#xff0c;运行应用程序注意 简介 使用Android Studio编写的简单Android 登录应用程序&#xff0c;该应用程序包含一个登录界面&#xff0c;具有账号和密码两个文本框&#xff0…...

C++_ C++11的override和final

文章目录 1. override 关键字2. final 关键字在虚函数上使用 final在类上使用 final 1. override 关键字 用于明确表示派生类中的某个虚函数是用来重写基类中的虚函数的&#xff0c;这样编译器会检查基类&#xff0c;看看是否确实存在同样的虚函数&#xff0c;如果没有匹配&am…...

【MyBatis源码】SQL 语句构建器AbstractSQL

文章目录 介绍org.apache.ibatis.jdbc.SQLSQL类使用示例SelectProvider搭配动态SQLAbstractSQL类源码分析 介绍 当我们需要使用Statement对象执行SQL时&#xff0c;SQL语句会嵌入Java代码中。SQL语句比较复杂时&#xff0c;我们可能会在代码中对SQL语句进行拼接&#xff0c;查…...

C++OJ_二叉树的层序遍历

✨✨ 欢迎大家来到小伞的大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;C_OJ 小伞的主页&#xff1a;xiaosan_blog 二叉树的层序遍历 102. 二叉树的层序遍历 - 力扣&#xff08;LeetCode&#xff0…...

什么是直方图算法

什么是直方图算法&#xff1f; 直方图算法是一种优化决策树分裂点搜索效率的算法&#xff0c;被广泛应用于像 LightGBM 和 XGBoost 这样的梯度提升决策树框架中。其核心思想是通过将连续特征的取值范围离散化为有限的区间&#xff08;称为 bins&#xff09;&#xff0c;在这些…...

pg_dump -Fc 导出的自定义格式数据库文件 相关操作

实例 将 test.dmp 文件转换为普通SQL内容, 并打印到屏幕 pg_restore -U postgres -Fc -f - test.dump将 test.dmp 文件转换为普通SQL内容, 并输出到 test.sql 文件中 pg_restore -U postgres -Fc -f test.sql -v test.dump备份得到自定义格式的数据库文件(dmp) pg_dump -U…...

Oh My Posh安装

nullSet up your terminalhttps://ohmyposh.dev/docs/installation/windows Git ee oh-my-posh: Windows上的oh-my-zsh&#xff0c;源地址 https://github.com/JanDeDobbeleer/oh-my-posh.git (gitee.com)https://gitee.com/efluent/oh-my-posh...

Node.js——fs模块-文件夹操作

1、借助Node.js的能力&#xff0c;我们可以对文件夹进行创建、读取、删除等操作 2、方法 方法 说明 mkdir/mkdirSync 创建文件夹 readdir/readdirSync 读取文件夹 rmdir/rmdirSync 删除文件夹 3、语法 其余的方法语法类似 本文的分享到此结束&#xff0c;欢迎大家评论区…...

15分钟学 Go 实战项目三 : 实时聊天室(学习WebSocket并发处理)

实时聊天室&#xff1a;学习WebSocket并发处理 目标概述 在本项目中&#xff0c;我们将创建一个实时聊天室&#xff0c;使用Go语言和WebSocket来处理并发消息交流。这将帮助你深入理解WebSocket协议的工作原理以及如何在Go中实现并发处理。 1. 项目需求 功能需求 用户可以…...

架构评估的方法

三种评估方法※ 第一是基于问卷(检查表)的方式,通过问卷调查对系统比较熟悉的相关人员,这种方式主观性很强。 专家问卷评估、用户问卷评估、内部团队问卷评估 第二是基于度量的方式,对系统指标完全量化,基于量化指标评价系统,这种方式需要评估者对系统非常熟悉。 软件质…...

羲和数据集收集器1.0

为了提升问答对的提取能力并完善GUI,我们从以下几个方面进行改进: 增强文本清理和解析能力:确保能够更准确地识别问答对。 支持更多文件格式:除了现有的 .txt, .docx, 和 .pdf,可以考虑支持其他常见格式如 .xlsx 等。 优化GUI设计:提供更友好的用户界面,包括进度条、日…...

ENSP OSPF和BGP引入

路由协议分为&#xff1a;内部网关协议和外部网关协议。内部网关协议用于自治系统内部的路由&#xff0c;包括&#xff1a;RIP和OSPF。外部网关协议用于自治系统之间的路由&#xff0c;包括BGP。内部网关协议和外部网关协议配合来共同完成网络的路由。 BGP:边界网关路由协议(b…...