JavaAOP动态代理详细介绍
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);
/
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动态代理内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341