OOP(面向对象)的补充,降低代码耦合度
AOP 实现分类
1.静态AOP
AOP 框架在编译阶段对程序源代码进行修改,生成了静态的 AOP 代理类(生成的 *.class 文件已经被改掉了,需要使用特定的编译器),比如 AspectJ。
2.动态AOP
AOP 框架在运行阶段对动态生成代理对象(在内存中以 JDK 动态代理,或 CGlib 动态地生成 AOP 代理类),如 SpringAOP。
- 静态代理
- 动态代理:JDK和CGLIB
- Spring AOP
- Spring+AspectJ
代理类和被代理的类实现了同样的接口,代理类同时持有被代理类的引用,这样,当我们需要调用被代理类的方法时,可以通过调用代理类的方法来做到
package com.example.kafka.tes;
import com.example.kafka.tes.service.UserService;
import com.example.kafka.tes.service.impl.DevelopImpl;
import com.example.kafka.tes.service.impl.UserServiceImpl;
public class MainProxyTest {
public static void main(String[] args) {
// 静态代理:代理方(DevelopImpl) / 被代理方(UserServiceImpl)
UserService staticUserService = new DevelopImpl(new UserServiceImpl());
staticUserService.addUser("test");
}
}
自定义接口:UserService
package com.example.kafka.tes.service;
public interface UserService {
boolean addUser(String userName);
boolean delUser(Integer id);
}
被代理类:UserServiceImpl
package com.example.kafka.tes.service.impl;
import com.example.kafka.tes.service.UserService;
public class UserServiceImpl implements UserService {
@Override
public boolean addUser(String userName) {
System.out.println("新增用户:"+userName);
return true;
}
@Override
public boolean delUser(Integer id) {
System.out.println("删除用户id:"+id);
return true;
}
}
代理类:DevelopImpl
package com.example.kafka.tes.service.impl;
import com.example.kafka.tes.service.UserService;
public class DevelopImpl implements UserService {
private UserService userService;
public DevelopImpl(Object obj){
this.userService = (UserService) obj;
}
@Override
public boolean addUser(String userName) {
System.out.println("Developer 完成后自己调用");
userService.addUser("Developer");
return false;
}
@Override
public boolean delUser(Integer id) {
System.out.println("Developer 完成后自己调用");
userService.delUser(1000);
return false;
}
}
动态代理:JDK和CGLIB
1.JDK动态代理:利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
2.CGlib动态代理:利用ASM(开源的Java字节码编辑库,操作字节码)开源包,将代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
区别:
JDK代理只能对实现接口的类生成代理;
CGlib是对类的实现代理,对指定的类生成一个子类,并覆盖其中的方法,这种通过继承类的实现方式,不能代理final修饰的类
service:
package com.example.kafka.tes.service;
public interface UserService {
boolean addUser(String userName);
boolean delUser(Integer id);
}
serviceImpl
package com.example.kafka.tes.service.impl;
import com.example.kafka.tes.service.UserService;
public class UserServiceImpl implements UserService {
@Override
public boolean addUser(String userName) {
System.out.println("新增用户:"+userName);
return true;
}
@Override
public boolean delUser(Integer id) {
System.out.println("删除用户id:"+id);
return true;
}
}
CGLIBProxy
package com.example.kafka.tes.proxy;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CGLIBProxy implements MethodInterceptor {
// CGlib需要代理的目标对象
private Object targetObject;
public Object createProxyObject(Object obj) {
this.targetObject = obj;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(obj.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object obj;
// 过滤方法
// 进行逻辑处理的函数
if (method.getName().equals("addUser")){
System.out.println("CGLIBProxy 增强 addUser() 方法!");
}
if (method.getName().equals("delUser")){
System.out.println("CGLIBProxy 增强 delUser() 方法!");
}
obj = method.invoke(targetObject, args);
return obj;
}
}
JDKProxy
package com.example.kafka.tes.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JDKProxy implements InvocationHandler {
private Object targetObject;
public Object newProxy(Object targetObject) {
// 将目标对象传入进行代理
this.targetObject = targetObject;
// 返回代理对象
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 进行逻辑处理的函数
if (method.getName().equals("addUser")){
System.out.println("JDKProxy 增强 addUser() 方法!");
}
if (method.getName().equals("delUser")){
System.out.println("JDKProxy 增强 delUser() 方法!");
}
Object ret;
// 调用invoke方法
ret = method.invoke(targetObject, args);
return ret;
}
}
Test
package com.example.kafka.tes;
import com.example.kafka.tes.proxy.CGLIBProxy;
import com.example.kafka.tes.proxy.JDKProxy;
import com.example.kafka.tes.service.UserService;
import com.example.kafka.tes.service.impl.UserServiceImpl;
public class MainProxyTest {
public static void main(String[] args) {
UserService userManager = (UserService)new CGLIBProxy().createProxyObject(new UserServiceImpl());
System.out.println("CGLibProxy:");
userManager.addUser("liHaoZhen");
System.out.println("JDKProxy:");
JDKProxy jdkProxy = new JDKProxy();
UserService userManagerJDK = (UserService)jdkProxy.newProxy(new UserServiceImpl());
userManagerJDK.addUser("HaoZhen");
}
}
Spring AOP
自定义切面(记录下日志)
package com.example.kafka.tes.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Aspect
@Component
public class CommonAspect {
@Pointcut("execution(public * com..*.service.impl..*.*(..))")
public void log() {
}
@Before("log()")
public void Before(JoinPoint joinPoint) {
Class extends JoinPoint> aClass = joinPoint.getClass();
System.out.println(aClass.getName());
}
@After("log() && @annotation(OperationLog)")
public void After(JoinPoint joinPoint) {
}
@AfterReturning("log()")
public void AfterReturning(JoinPoint joinPoint) {
Class extends JoinPoint> aClass = joinPoint.getClass();
System.out.println(aClass.getName());
}
@AfterThrowing("log()")
public void AfterThrowing(JoinPoint joinPoint) {
Class extends JoinPoint> aClass = joinPoint.getClass();
System.out.println(aClass.getName());
}
@Around("@annotation(OperationLog)")
public Object Around(ProceedingJoinPoint joinPoint,OperationLog OperationLog) throws Throwable {
String name = OperationLog.name();
System.out.println(name);
long startTime = System.currentTimeMillis();
//获取当前请求对象
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
assert attributes != null;
HttpServletRequest request = attributes.getRequest();
// TODO 记录请求信息
return joinPoint.proceed();
}
private Object getParameter(Method method, Object[] args) {
List
自定义注解(切入点可以使用 @Pointcut注解指定 或 该自定义的注解)
package com.example.kafka.tes.aspect;
import java.lang.annotation.*;
@documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface OperationLog {
String name();//调用接口的名称
boolean intoDb() default false;//该条操作日志是否需要持久化存储
}



