AOP是一种设计思想,是软件设计领域中的面向切面编程,它是面向对象编程的一种补充和完善。本文将用Java实现AOP代理的三种方式,需要的可以参考一下
1.IOC与AOP概念
IOC:控制反转,把对象创建和对象之间的调用过程,交给Spring进行管理。使用IOC的目的是为了降低耦合度。
AOP:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。AOP的底层实现是基于动态代理(实现方式是当切入接口时,使用JDK原生动态代理;当切入普通方法时,使用cglib动态代理)。
2.为何使用动态代理
随着业务的不断扩展:
(1)日志功能:如果日志代码修改,需要修改多处。
(2)校验功能:如果多处需要校验,需要修改多处。
这时就需要使用动态代理来解决问题,动态代理的实现方式有两种:
[1]JDK原生动态代理:缺点是必须基于接口完成
[2]cglib动态代理:他可以不用基于接口完成
2.1 JDK原生动态代理
2.1.1 MathService接口类
public interface MathService {
//+
public Double add(double a,double b);
//-
public Double sub(double a,double b);
//*
public Double mul(double a,double b);
///
public Double div(double a,double b);
}
2.1.2 MathServiceImpl实现接口类
public class MathServiceImpl implements MathService{
@Override
public Double add(double a, double b) {
Double result=a+b;
return result;
}
@Override
public Double sub(double a, double b) {
Double result=a-b;
return result;
}
@Override
public Double mul(double a, double b) {
Double result=a*b;
return result;
}
@Override
public Double div(double a, double b) {
Double result=a/b;
return result;
}
}
2.1.3 ProxyFactory动态代理工厂
public class ProxyFactory {
//被代理对象
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
//获取代理对象
public Object getProxy(){
/**
* ClassLoader loader, 被代理对象的类加载器
* Class<?>[] interfaces, 被代理对象实现的接口
* InvocationHandler h: 当代理对象执行被代理的方法时,会触发该对象中的invoke功能
*/
ClassLoader loader=target.getClass().getClassLoader();
Class<?>[] interfaces=target.getClass().getInterfaces();
InvocationHandler h=new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//可以加上需要的非业务代码
//method.getName()获取方法名
// Arrays.asList(args)获取输入值
System.out.println("this is "+method.getName()+" method begin with"+ Arrays.asList(args));
//method:表示代理对象要代理的方法
//invoke:回调该函数
//args:方法需要的参数
Object result = method.invoke(target, args);//代理对象回调该方法
return result;
}
};
//先写此处方法,才可找到上述三个方法填写方式
Object o = Proxy.newProxyInstance(loader, interfaces, h);
return o;
}
}
2.1.4 测试类
public class Test01 {
public static void main(String[] args) {
MathServiceImpl target=new MathServiceImpl();
ProxyFactory proxyFactory=new ProxyFactory(target);
MathService proxy = (MathService) proxyFactory.getProxy();
Double add = proxy.add(15.0, 5.0);
System.out.println(add);
}
}
2.2 cglib动态代理
2.2.1 MathServiceImpl类
public class MathServiceImpl{
public Double add(double a, double b) {
Double result=a+b;
return result;
}
public Double sub(double a, double b) {
Double result=a-b;
return result;
}
public Double mul(double a, double b) {
Double result=a*b;
return result;
}
public Double div(double a, double b) {
Double result=a/b;
return result;
}
}
2.2.2 ProxyFactory动态代理工厂
注意:
(1)引入cglib的jar包.
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.5</version>
</dependency>
(2)创建一个代理类工厂并实现接口MethodInterceptor
public class ProxyFactory implements MethodInterceptor {
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
//获取代理对象
public Object getProxy(){
Enhancer enhancer=new Enhancer();
//指定被代理对象的父类
enhancer.setSuperclass(target.getClass());
//指定回调类
enhancer.setCallback(this);
//创建代理对象
return enhancer.create();
}
//当代理对象执行代理方法时触发的方法
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
// System.out.println("before++++++++++++++++++++");
// Object result = method.invoke(target, args);
//可以加上需要的非业务代码
//method.getName()获取方法名
// Arrays.asList(args)获取输入值
System.out.println("this is "+method.getName()+" method begin with"+ Arrays.asList(args));
//method:表示代理对象要代理的方法
//invoke:回调该函数
//args:方法需要的参数
Object result = method.invoke(target, args);//代理对象回调该方法
return result;
}
}
2.2.3 测试类
public class Test01 {
public static void main(String[] args) {
MathServiceImpl target=new MathServiceImpl();
ProxyFactory proxyFactory=new ProxyFactory(target);
MathServiceImpl proxy = (MathServiceImpl) proxyFactory.getProxy();
Double add = proxy.add(1, 2);
System.out.println(add);
}
}
3.AOP动态代理
3.1 添加对应依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.15.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.15.RELEASE</version>
</dependency>
3.2 配置spring.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--包扫描-->
<context:component-scan base-package="com.qy151wd.proxy.proxy.aop"/>
<!--开启aop注解-->
<aop:aspectj-autoproxy/>
</beans>
3.3 MathService接口类
public interface MathService {
public Double add(double a, double b);
public Double sub(double a, double b);
public Double mul(double a, double b);
public Double div(double a, double b);
}
3.4 MathServiceImpl实现接口类
@Service
public class MathServiceImpl implements MathService {
@Override
public Double add(double a, double b) {
Double result=a+b;
return result;
}
@Override
public Double sub(double a, double b) {
Double result=a-b;
return result;
}
@Override
public Double mul(double a, double b) {
Double result=a*b;
return result;
}
@Override
public Double div(double a, double b) {
Double result=a/b;
return result;
}
}
3.5 LogAspect类
@Service //若是使用@component也可以
@Aspect //表示该类为切面类
public class LogAspect {
//任意返回类型 aop包下的所有类都有切面日志 使用通配符
//第一个*:修饰符和返回值类型
//第二个*:所有类
//第三个*:所有方法
@Before("execution(* com.qy151wd.proxy.proxy.aop.*.*(..))")
public void before(){
System.out.println("方法执行前的日志");
}
@After("execution(* com.qy151wd.proxy.proxy.aop.*.*(..))") //总会被执行,不管有没有异常
public void after(){
System.out.println("方法执行后的日志");
}
@AfterReturning("execution(* com.qy151wd.proxy.proxy.aop.*.*(..))")//只有碰到return后才会执行
public void afterReturning(){
System.out.println("碰到return后执行");
}
@AfterThrowing("execution(* com.qy151wd.proxy.proxy.aop.*.*(..))")//异常通知
public void afterThrowing(){
System.out.println("出现异常了");
}
}
3.6 测试类
public class Test01 {
public static void main(String[] args) {
//从spring容器中获取
ApplicationContext app=new ClassPathXmlApplicationContext("spring.xml");
MathService mathService = (MathService) app.getBean("mathServiceImpl");
Double add = mathService.add(10, 5);
System.out.println(add);
}
}
到此这篇关于Java AOP动态代理详细介绍的文章就介绍到这了,更多相关Java AOP动态代理内容请搜索编程学习网以前的文章希望大家以后多多支持编程学习网!
本文标题为:Java AOP动态代理详细介绍
- value & 是什么意思?0xff 在 Java 中做什么? 2022-01-01
- Java包名称中单词分隔符的约定是什么? 2022-01-01
- Eclipse 插件更新错误日志在哪里? 2022-01-01
- 将log4j 1.2配置转换为log4j 2配置 2022-01-01
- Jersey REST 客户端:发布多部分数据 2022-01-01
- Safepoint+stats 日志,输出 JDK12 中没有 vmop 操作 2022-01-01
- Spring Boot连接到使用仲裁器运行的MongoDB副本集 2022-01-01
- C++ 和 Java 进程之间的共享内存 2022-01-01
- 从 finally 块返回时 Java 的奇怪行为 2022-01-01
- 如何使用WebFilter实现授权头检查 2022-01-01