# 1 - 继承 - CGLIB (Code Generator Library)

Spring MVC DispatcherServlet- 调用原理

这里介绍的 AOP 继承对象 - 原理

Spring MVC - DespacterServlet - 简化 / 模仿

package com.edut.springboot.test;

import java.util.ArrayList;
import java.util.List;

/** * /Springmvn - DispatcherServlet (简化 - 模仿) */


//=======================================
//查询服务
interface SearchService{
	Object doSearch(String key ) ; 
}

class DefaultSearchService implements SearchService {

	@Override
	public Object doSearch(String key) {
		//参数校验
		//数据访问
		//结果处理 
		System.out.println("search by "+key);
		return null;
	}
}


//===========================================
//扩展服务
interface Interceptor{//扩展业务拦截
	void doBefore() ;//{} ;jdk8 不允许 接口有 方法体 
	void doAfter() ;// {} ; jdk9 允许
}

class LogInterceptor implements Interceptor { //日志业务
	@Override
	public void doBefore() {
		System.out.println("start - [Interceptor] :"+System.currentTimeMillis());
	}
	@Override
	public void doAfter() {
		System.out.println("end - [Interceptor] :"+System.currentTimeMillis());		
	}
}

class PermissionInterceptor  implements Interceptor {//验证业务
	@Override
	public void doBefore() {
		System.out.println("check permission - Permission[Interceptor]");
	}
	@Override
	public void doAfter() {
	}
}

//.....
//日志扩展:计时
class ChildDefaultSearchService extends DefaultSearchService {
	
	private List<Interceptor> interceptors ; 
	
	
	public ChildDefaultSearchService(List<Interceptor> interceptors) {
		this.interceptors = interceptors ; 
	}
	
	@Override
	public Object doSearch(String key) {
		interceptors.forEach(i -> i.doBefore());
		
		System.out.println("start - ChildDefault[SearchService] :"+ System.currentTimeMillis());
		Object result = super.doSearch(key);//目标方法
		System.out.println("end - ChildDefault[SearchService] :"+ System.currentTimeMillis());
		
		interceptors.forEach(i -> i.doAfter());
		return result;
	}
}

//权限扩展:检查权限
class PermissionLogDefaultSearchService extends ChildDefaultSearchService{
	
	public PermissionLogDefaultSearchService(List<Interceptor> interceptors) {
		super(interceptors);
	}


	@Override
	public Object doSearch(String key) {
		System.out.println("check permission - PermissionLogDefault[SearchService]");
		return super.doSearch(key);
	}
}

public class TestExtends01 {
	public static void main(String[] args) {
		List<Interceptor> interceptors = new ArrayList<>() ;
		interceptors.add(new PermissionInterceptor()) ; 
		interceptors.add(new LogInterceptor()) ; 
		
		PermissionLogDefaultSearchService service = new PermissionLogDefaultSearchService(interceptors);
		service.doSearch("!!!!!! TestExtends01 !!!!!!!") ; 
	}
}

# 2 - 组合对象 - compose - JDK

这里介绍的 AOP 组合对象 - 原理

基于上面代码。继续业务扩展


package com.edut.springboot.test;

import java.util.ArrayList;
import java.util.List;

//============
//核心业务
interface MailService {
	void send(String msg) ;
}

class DefaultMailService implements MailService {
	@Override
	public void send(String msg) {
		System.out.println(msg);
	}
}
//============================================
//扩展业务

//from class TestExtends01 

//==================================
//组合对象
class ComposeMailService implements MailService {//is a
	//has a
	private MailService mailService ; 
	private List<Interceptor> interceptors ;
	
	public ComposeMailService( MailService mailService , List<Interceptor> interceptors ) {
		this.mailService = mailService;
		this.interceptors = interceptors ; 
				
	}
	
	@Override
	public void send(String msg) {
		interceptors.forEach(i -> i.doBefore());
		
		mailService.send(msg); //核心业务
		
		interceptors.forEach(i -> i.doAfter());
	}
	
}


//======================================
public class TestCompose01 {
	public static void main(String[] args) {
		List<Interceptor> interceptors = new ArrayList<Interceptor>() ;
		interceptors.add(new PermissionInterceptor()) ;
		interceptors.add(new LogInterceptor() ) ;
		
		ComposeMailService service = new ComposeMailService( new DefaultMailService() , interceptors);
		service.send("新年快乐!");
		
	}
}



# AspectJ - ProceedingJoinPoint 细节

  • <mark>继承对象</mark> 实现 AOP ⇒ ProceedingJoinPoint.getSignature定位到 - <mark>实现方法</mark>
  • <mark>组合对象</mark> 实现 AOP ⇒ ProceedingJoinPoint.getSignature 定位到 - <mark>接口方法</mark>(接口

所以,如果 在 <mark>实现的方法上加了注解</mark>,在 <mark>组合对象实现</mark> 上,是无法获取的。
如下:


希望:组合对象方法 - AOP 获取实现上的接口 

@Aspect
@Component
@Slf4j
public class SysLogAspect {

	@Autowired
	private SysLogService sysLogService ;
	
	//sysLogServiceImpl
	@Pointcut("bean(sysUserServiceImpl)")
	public void joinPoint() {} ; 
	
	@Around("joinPoint()")
	public Object around(ProceedingJoinPoint pj ) throws Throwable {
		try {
			
			long start = System.currentTimeMillis(); 
			Object result = pj.proceed();
			long  end = System.currentTimeMillis() ; 
			
			saveLog(pj , end-start) ;    <------ 这里 继续  
														↓
			return result ;} catch (Throwable e) {							↓
			log.error(e.getMessage());throw e;}}private void saveLog(ProceedingJoinPoint pj, long time) throws NoSuchMethodException, SecurityException {

						问题在这里(直接用注册类获取方法)-> 只能拿到接口中的方法(而注释在实现上)			
							↓							
		MethodSignature signature =(MethodSignature) pj.getSignature(); // (MethodSignature) : 提供了参数的 字符串到类型的转换
		Object target = pj.getTarget(); 

		Method method  = signature.getMethod() ;
		
						null	!!! 
						  ↓
		RequiredLog annotation = method.getAnnotation(RequiredLog.class);

	
	}
	
}


实现类(部分)

@Service
public class SysUserServiceImpl implements SysUserService {
	
@RequiredLog(operation = "禁用按钮点击")
	@Override
	public int validById(Integer id, Integer valid) {

配置

spring:
  aop:
    proxy-target-class: false 

# AspectJ - ProceedingJoinPoint 细节 - 总结

## 解决方法 1 : 通过 Class 类获得 Method


希望:组合对象方法 - AOP 获取实现上的接口 

@Aspect
@Component
@Slf4j
public class SysLogAspect {

	@Autowired
	private SysLogService sysLogService ;
	
	//sysLogServiceImpl
	@Pointcut("bean(sysUserServiceImpl)")
	public void joinPoint() {} ; 
	
	@Around("joinPoint()")
	public Object around(ProceedingJoinPoint pj ) throws Throwable {
		try {
			
			long start = System.currentTimeMillis(); 
			Object result = pj.proceed();
			long  end = System.currentTimeMillis() ; 
			
			saveLog(pj , end-start) ;    <------ 这里 继续  
														↓
			return result ;} catch (Throwable e) {							↓
			log.error(e.getMessage());throw e;}}private void saveLog(ProceedingJoinPoint pj, long time) throws NoSuchMethodException, SecurityException {

						问题在这里(直接用注册类获取方法)-> 只能拿到接口中的方法(而注释在实现上)			
							↓							
		MethodSignature signature =(MethodSignature) pj.getSignature(); // (MethodSignature) : 提供了参数的 字符串到类型的转换
		Object target = pj.getTarget(); 
		
					通过类获取到方法(因为类指向的是 实现的类!!)
						↓
		//Method method = signature.getMethod() ;
		Class<?> clazz = target.getClass(); // 实现 - 类
		Method method = clazz.getDeclaredMethod(signature.getName() , signature.getParameterTypes());

		RequiredLog annotation = method.getAnnotation(RequiredLog.class);

	
	}
	
}


## 解决方法 2 : 用继承对象 AOP


修改 - 配置 (默认也是 true)

spring:
  aop:
    proxy-target-class: true