AOP面向切面编程
也是一种编程思想。主要的工作就是对应用当中重复的代码进行横向抽取。在运行过程之中,采用的是动态代理技术把一些代码内容植入到应用当中。主要是植入到目标方法当中进行增强。
在Spring中有两种代理模式。(AOP就是基于动态代理来实现的,底层依赖于反射机制)
- JDK原生 动态代理
首先先在pom.xml里面映入c3p0依赖
<!--引入C3P0-->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
/**
* @author: admin
* @date: 2021/3/4
*
* JDK 原生的
*
* 主要是对应用当中的业务层进行增强
* Proxy jdk的一个代理类
* 使用该类中的一个方法 newProxyInstance() 构建目标对象的代理对象
* 该方法中有三个参数:
* ClassLoader: 类加载器 要求和目标对象是一样的类加载器 固定写法
* Class<?> interfaces: 实现的接口,要求和目标对象中实现的接口一样 固定写法
* InvocationHandle: 代理的方式 如何对目标对象进行增强 接口 匿名内部类
* 在该接口当中定义了一个抽象方法 invoke()
* 在该方法中也有三个参数:
* Object proxy: 代理的目标对象
* Method method: 当前要执行的目标对象中的方法
* Object[] args: 当前执行方法中用到的参数。
*/
@Component("proxy01")
public class Proxy01 {
//定义一个方法
public UserService getProxyUserService(UserService userService) {// UserService 接口 传入的参数值肯定是该接口的实现类
UserService us = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(), UserServiceImpl.class.getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("queryUserByUsername该方法开始执行了。。。。");
Object obj = method.invoke(userService, args);// 反射机制 queryUserByUsername
System.out.println("queryUserByUsername该方法执行即将完毕。。。。。");
return obj;
}
});
return us;
}
/*@Autowired
private UserService userService;*/
public static void main(String[] args) throws SQLException {
Proxy01 proxy01 = new Proxy01();
UserService proxyUserService = proxy01.getProxyUserService(new UserServiceImpl());
User user = proxyUserService.queryUserByUsername("小苏");
System.out.println(user);
}
}
- 第三方插件 cglib代理
首先在pom.xml里面引入cglib的依赖
<!--引入第三方cglib依赖-->
<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
测试代码
/**
* @author: admin
* @date: 2021/3/4
*
* 测试 动态代理 第二种方式 cglib
*
* 原理: 不需要借助于接口,一般情况下在继承关系中 --->父子类
* 要求: 目标类 不能是最终类 public final DemoClass {} 不能出现final
* Enhancer 增强器类
* create() 创建目标对象的代理对象
* 参数:
* class 字节码对象 目标对象中的字节码对象
* callback ----> MethodInterceptor接口 方法拦截器 代理的方式
* 通过拦截器的方式实现对目标对象中的方法进行增强。
* 采用匿名内部类的方式实现
* import net.sf.cglib.proxy.MethodInterceptor;
* MethodInterceptor定义了一个抽象方法
* intercept() 拦截方法
* 拦截方法也有三个参数:
* Object proxy: 代理的目标对象
* Method method: 当前要执行的目标对象中的方法
* Object[] objects: 当前执行方法中用到的参数。
*
*/
@Component("proxy02")
public class Proxy02 {
// 定义一个方法
public UserService getProxyUserService(UserService us){
// us.getClass() 获取字节码对象
UserService userService = (UserService) Enhancer.create(us.getClass(), new MethodInterceptor() {
//intercept 拦截器
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("开启事务。。。");// connection.setAutoCommit()
Object obj = method.invoke(us, objects);
System.out.println("提交事务。。。"); // commit()
return obj;
}
});
return userService;
}
}