回顾SpringAop

首先回顾几个名词,能用通俗的话来讲就用通俗的来讲

切面:比如事务,我们要把它单独模块化出来实现,不想影响业务逻辑,那么这个时候我们给业务逻辑添加进入这个事务的功能,它就是切面

连接点:可以让切面具体实现的一些位置集合称为连接点

切点:具体切面切入的位置,为切点

通知:切面要完成的工作,比如事务,保存数据库的正确操作

引入:向现有的类添加属性合方法

织入:把切面应用到目标对象,并创建新的代理对象的过程,在目标对象生命周期里有多个点可以织入:1.编译器 2.类加载器 3.运行期


Spring提供了4种类型的AOP支持

1.基于代理的经典SpringAop

2.纯POJO切面

3.@AspectJ注解驱动的切面

4.注入式AspectJ切面

前3种Spring对AOP的直接局限于方法拦截


PS:Spring只有在需要应用到代理对象才创建它,但是Spring上下文加载后就会完成初始对象的创建


SpringAOP一般使用Spring结合AspectJ,但是SpringAOP并不能使用所有的AspectJ的功能


下面是Spring可以使用AspectJ的一些节点

arg(),@args(),execution(),this(),target(),@target(),within(),@within(),@annotation()


AspectJ有5个重要的通知

1.前置通知

2.后置通知

3.异常通知

4.返回通知

5.环绕通知


继续注解的形式贴上代码:

<运行结果>:

beforeAssit
start living...
afterAssit
returnAssit


I am in before
start having...
I am in returning
I am in after


next one:sam
welcome : sam

package Model;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class Assit {
	//自定义切点
	@Pointcut("execution(* Model.Hotel.live(..))")
	public void rest(){}
	@Pointcut("execution(* Model.Hotel.having(..))")
	public void having(){}
	@Pointcut("execution(* Model.Hotel.welcomeImportantPerson(String))"
			+ "&&args(name)")
	public void welcome(String name){}
	//前置通知 
	@Before("rest()")
	public void beforeAssit(){
		System.out.println("beforeAssit");
	}
	//后置通知
	@After("rest()")
	public void afterAssit(){
		System.out.println("afterAssit");
	}
	@AfterReturning("rest()")
	//返回通知
	public void returnAssit(){
		System.out.println("returnAssit");
	}
	@AfterThrowing("rest()")
	//异常通知
	public void exceptionAssit(){
		System.out.println("exceptionAssit");
	}
	//环绕通知
	@Around("having()")
	public void arroundAssit(ProceedingJoinPoint pp){
		System.out.println("I am in before");
		try {
			pp.proceed();
			System.out.println("I am in returning");
		} catch (Throwable e) {
			System.out.println("I am in exception");
			e.printStackTrace();
		}
		System.out.println("I am in after");
	}
	@Before("welcome(name)")
	public void beforeWelcome(String name){
		System.out.println("next one:"+name);
	}
}

package Model;

public interface Hotel {
	void live();
	void having();
	void welcomeImportantPerson(String name);
}

package Model;

import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

@Service("hi")
@Scope(scopeName = ConfigurableBeanFactory.SCOPE_SINGLETON)
public class HotelImp implements Hotel{

	@Override
	public void live() {
		// TODO Auto-generated method stub
		System.out.println("start living...");
	}

	@Override
	public void having() {
		// TODO Auto-generated method stub
		System.out.println("start having...");
	}

	@Override
	public void welcomeImportantPerson(String name) {
		// TODO Auto-generated method stub
		System.out.println("welcome : "+name);
	}
	
}





<think>好的,用户想了解Spring AOP的原理,特别是代理模式、动态代理和静态代理。首先,我需要回顾一下代理模式的基本概念,然后区分静态代理和动态代理的不同,再联系到Spring AOP是如何应用这些技术的。 首先,代理模式的定义。根据引用[1],代理模式允许在不修改被代理对象的情况下,通过代理类进行功能增强。这里的关键是代理类分为静态和动态两种。静态代理需要手动创建代理类,而动态代理在运行时生成。用户可能想知道这两种代理在Spring AOP中的应用场景。 接下来,静态代理的细节。引用[1]提到静态代理的类在运行前已经存在,通常由程序员手动编写或工具生成。例如,假设有一个业务接口Subject和实现类RealSubject,静态代理类Proxy会实现Subject并持有RealSubject的引用,在方法调用前后添加逻辑。这种情况的缺点是每个被代理类都需要一个对应的代理类,导致代码冗余。 然后是动态代理,Spring AOP主要使用JDK动态代理和CGLIB。引用[2]指出JDK代理通过Proxy类生成代理对象,而CGLIB通过Enhancer创建。JDK动态代理要求目标类实现接口,利用InvocationHandler的invoke方法进行增强。CGLIB则通过继承目标类,重写方法来实现代理,适用于没有接口的情况。需要解释这两种方式的区别以及Spring如何选择使用哪一种。 还要结合Spring AOP的源码,如引用[2]提到的AOP源码剖析部分。Spring在运行时决定使用哪种代理方式,如果目标类实现了接口,默认使用JDK代理,否则使用CGLIB。这涉及到AOP的配置和底层机制。 用户可能还关心AOP的应用场景,比如事务管理、日志记录等,这些通过代理模式实现,无需修改原有代码。需要举例说明,比如在方法执行前后加入事务控制,动态代理如何拦截方法调用并添加额外操作。 另外,需要确保回答结构清晰,分点说明原理、代理类型、实现方式以及Spring的选择策略。同时,生成的相关问题要围绕用户可能进一步询问的点,比如性能比较、配置方法或实际应用例子。 最后,检查引用是否正确应用,如引用[1]关于代理模式的分类,引用[2]关于Spring AOP的具体实现,引用[3]关于代理模式的角色。确保每个技术点都有对应的引用支持,增加回答的可信度。</think>### Spring AOP原理与代理模式解析 #### 一、代理模式的核心作用 代理模式通过代理对象控制对真实对象的访问,在**不修改原始代码**的前提下实现功能增强。其核心角色包括: - **Subject**:定义业务接口(可以是接口或抽象类)[^3] - **RealSubject**:具体业务实现类(被代理对象) - **Proxy**:代理类,负责增强和控制对RealSubject的访问 #### 二、静态代理的实现方式 静态代理需**手动编写代理类**,代理关系在编译时确定。例如: ```java // 业务接口 interface UserService { void save(); } // 真实对象 class UserServiceImpl implements UserService { public void save() { /* 业务逻辑 */ } } // 静态代理类 class UserServiceProxy implements UserService { private UserService target; public UserServiceProxy(UserService target) { this.target = target; } public void save() { System.out.println("前置增强"); target.save(); // 调用真实对象方法 System.out.println("后置增强"); } } ``` **缺点**:每个业务类需对应一个代理类,代码冗余度高[^1]。 #### 三、动态代理的实现机制 Spring AOP主要采用两种动态代理技术: 1. **JDK动态代理**(基于接口) - 要求目标类必须实现至少一个接口 - 通过`java.lang.reflect.Proxy`生成代理对象 - 核心类`InvocationHandler`实现方法拦截: ```java class JdkProxyHandler implements InvocationHandler { private Object target; public Object getProxy(Object target) { this.target = target; return Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); } public Object invoke(Object proxy, Method method, Object[] args) { System.out.println("前置增强"); Object result = method.invoke(target, args); System.out.println("后置增强"); return result; } } ``` 2. **CGLIB代理**(基于继承) - 通过生成目标类的子类实现代理 - 使用`MethodInterceptor`接口: ```java class CglibInterceptor implements MethodInterceptor { public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) { System.out.println("前置增强"); Object result = proxy.invokeSuper(obj, args); System.out.println("后置增强"); return result; } } // 通过Enhancer创建代理 Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(TargetClass.class); enhancer.setCallback(new CglibInterceptor()); TargetClass proxy = (TargetClass)enhancer.create(); ``` - **优势**:可代理无接口的类[^2] #### 四、Spring AOP的代理选择策略 | 条件 | 使用的代理方式 | |--------------------------|----------------| | 目标类实现了至少一个接口 | JDK动态代理 | | 目标类未实现任何接口 | CGLIB代理 | **底层实现**: - 通过`DefaultAopProxyFactory`类判断代理方式 - Spring Boot 2.x后默认强制使用CGLIB(可通过`spring.aop.proxy-target-class=true`配置) #### 五、AOP核心流程 1. 解析切面定义(@Aspect) 2. 匹配连接点(Pointcut) 3. 生成代理对象 4. 编织增强逻辑(Advice) 5. 通过责任链模式执行拦截器链 #### 六、性能对比 - **JDK动态代理**:生成速度快,执行效率稍低 - **CGLIB**:生成速度慢,执行效率高(现代JVM差距已不明显)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值