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动态代理详细介绍
基础教程推荐
- 在 Libgdx 中处理屏幕的正确方法 2022-01-01
- 减少 JVM 暂停时间 >1 秒使用 UseConcMarkSweepGC 2022-01-01
- FirebaseListAdapter 不推送聊天应用程序的单个项目 - Firebase-Ui 3.1 2022-01-01
- 设置 bean 时出现 Nullpointerexception 2022-01-01
- 如何使用 Java 创建 X509 证书? 2022-01-01
- “未找到匹配项"使用 matcher 的 group 方法时 2022-01-01
- 无法使用修饰符“public final"访问 java.util.Ha 2022-01-01
- Java:带有char数组的println给出乱码 2022-01-01
- 降序排序:Java Map 2022-01-01
- Java Keytool 导入证书后出错,"keytool error: java.io.FileNotFoundException &拒绝访问" 2022-01-01