什么是Aop
Aop是面向切面编程 Aspect Oriented Programming
面向切面是一种思想,它看似与面向对象相对,但实则为面向对象的延续。
Spring Aop原理
Spring AOP的原理是动态代理,通过对目标类的代理,完成功能代码的织入。
代理可分为静态代理和动态代理
静态代理
-
可在编译阶段对目标类织入增强代码;代码实现
-
典型有JDK静态代理和AspectJ
动态代理
-
在程序运行过程中,动态地为目标类织入增强代码。反射实现
-
典型有JDK动态代理和CGLib
Spring AOP采用JDK动态代理+CGLib的方式,使用二者结合体,原因是两种技术都有一点缺陷:
-
JDK动态代理: 目标类必须实现的某个接口,如果某个类没有实现接口则不能生成代理对象。
-
CGLib动态代理: 继承目标类来进行代理,因此目标类可以不实现接口,但要求目标类不是能是final。
jdk静态代理
代理类在编译期间就已经确定了,代理类是需要开发者自己定义,可能会存在多个代理类
interface UserService {
void addUser(String username, String password);
}
class UserServiceImpl implements UserService {
@Override
public void addUser(String username, String password) {
System.out.println(username + "用户添加成功");
}
}
class UserServiceProxy implements UserService {
private UserService userService;
public UserServiceProxy(UserService userService) {
this.userService = userService;
}
@Override
public void addUser(String username, String password) {
System.out.println("打印日志1");
userService.addUser(username, password);
System.out.println("打印日志2");
}
}
class Main1 {
public static void main(String[] args) {
UserServiceProxy u = new UserServiceProxy(new UserServiceImpl());
u.addUser("zd", "123");
}
}
缺点:会增加很多个代理类
jdk动态代理
具体代理类型需要在运行期间确定,开发者不需要自己实现代理类
interface UserService {
void addUser(String username, String password);
}
interface DeptService {
void addDept(String deptName);
}
class UserServiceImpl implements UserService {
@Override
public void addUser(String username, String password) {
System.out.println(username + "用户添加成功");
}
}
class DeptServiceImpl implements DeptService {
@Override
public void addDept(String username) {
System.out.println(username + "部门添加成功");
}
}
class JdkDynamicProxy implements InvocationHandler {
private Object object;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("日志1");
Object invoke = method.invoke(object, args);
System.out.println("日志2");
return invoke;
}
public Object newProxyInstance(Object obj) {
this.object = obj;
Object o =
Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
return o;
}
}
class Main2 {
public static void main(String[] args) {
JdkDynamicProxy u = new JdkDynamicProxy();
UserService o = (UserService) u.newProxyInstance(new UserServiceImpl());
o.addUser("ls", "1234");
DeptService o1 = (DeptService) u.newProxyInstance(new DeptServiceImpl());
o1.addDept("销售部");
}
}
缺点:
JDK动态代理: 目标类必须实现的某个接口,如果某个类没有实现接口则不能生成代理对象。
CGLib动态代理:继承目标类来进行代理,因此目标类可以不实现接口,但要求目标类不是能是final。
CGLIB动态代理
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.1</version>
</dependency>
package com.example.dymicproxy.cglibdynamicProxy;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public interface UseService {
void addUser(String username, String password);
}
class UseServiceImpl implements UseService {
@Override
public void addUser(String username, String password) {
System.out.println(username + "用户添加成功");
}
}
class CglibProxy implements MethodInterceptor {
public Enhancer enhancer = new Enhancer();
public Object getDaoBean(Class cls) {
enhancer.setSuperclass(cls);
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) {
System.out.println("日志1");
Object o1 = methodProxy.invokeSuper(o, objects);
System.out.println("日志2");
return o1;
}
}
class Main3 {
public static void main(String[] args) {
CglibProxy u = new CglibProxy();
UseService daoBean = (UseService) u.getDaoBean(UseServiceImpl.class);
daoBean.addUser("qqq", "1212");
}
}
缺点:
JDK动态代理: 目标类必须实现的某个接口,如果某个类没有实现接口则不能生成代理对象。
CGLib动态代理:继承目标类来进行代理,因此目标类可以不实现接口,但要求目标类不是能是final。