Java spring AOP(面向切面编程) JDK动态代理示例
本文引用B站老师(“一个体面的人”发布的视频) spring框架教程相关内容,适合初学者理解使用
了解更多内容点击链接.
AOP概念:
(百度百科)
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
JDK动态代理,可简单的理解为将advice(增强)和到target(目标类)织入代理中,在每次执行目标类方法时,都会动态的执行对应的增强方法。在本示例中,即将切面类的before方法和after方法,通过spring工厂中的代理proxService,加到每个目标方法前、后执行。
目标类
目标类接口
文件名:UserService.java
package com.itheima.a_proxy.a_jdk;
/*目标类接口*/
public interface UserService {
public void addUser();
public void updateUser();
public void deleteUser();
}
目标类实现
文件名:UserServiceImpl.java
package com.itheima.a_proxy.a_jdk;
/*目标类实现*/
public class UserServiceImpl implements UserService {
@Override
public void addUser(){
System.out.println("a_proxy.a_jdk addUser");
}
@Override
public void updateUser(){
System.out.println("a_proxy.a_jdk updateUser");
}
@Override
public void deleteUser(){
System.out.println("a_proxy.a_jdk deleteUser");
}
}
切面类
切面类含有before方法和after方法
文件名:MyAspect.java
package com.itheima.a_proxy.a_jdk;
/*切面类*/
public class MyAspect {
public void before(){
System.out.println("前方法");
}
public void after(){
System.out.println("后方法");
}
}
spring工厂
文件名:MyBeanFactory.java
package com.itheima.a_proxy.a_jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class MyBeanFactory {
public static UserService createService(){
//return new UserServiceImpl();
//1.目标类,匿名类前加final
final UserService userService = new UserServiceImpl();
//2.切面类
final MyAspect myAspect = new MyAspect();
/*3.代理类:将目标类(切入点)和切面类(通知)结合,即切面
*Proxy.newProxyInstance(loader,interfaces,h)
* 参数1:loader,类加载器,动态代理类运行时创建,任何类都需要类加载器将其加载到内存。
* 一般情况:当前类.class.getClassLoader();
* 目标类实例.getClass.get...
* 参数2:interfaces,代理类需要实现的所有接口
* 方式1:目标类实例.getClass().getInterfaces();注意,只能获得自己的接口,不能获得父类元素的接口
* 方式2:new Class[]{UserService.class} 例如:jsbc驱动 DriverManager 获得接口Connection
* 参数3:InvocationHandler 处理类,接口,必须进行实现类,一般采用匿名内部
* 提供invoke(Object proxy, Method method, Object[] args)方法:代理类的每一个方法执行时,都将调用一次invoke
* 参数(1)Object proxy:代理对象
* 参数(2)Method method:代理对象当前执行的方法的描述对象(反射)
* 执行方法名获得:method.getName()
* 执行方法:method.invoke(对象,实际参数)
* 参数(3)Object[] args:方法实际参数
* */
UserService proxService = (UserService) Proxy.newProxyInstance(
MyBeanFactory.class.getClassLoader(),
userService.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//将目标类和切面类结合
//前执行
myAspect.before();
//执行目标方法
Object obj = method.invoke(userService,args);
//后执行
myAspect.after();
return obj;
}
});
return proxService;
}
}
测试
文件名:TestJDK.java
package com.itheima.a_proxy.a_jdk;
import org.junit.Test;
import org.springframework.test.context.TestExecutionListeners;
public class TestJDK {
@Test
public void demo01(){
UserService userService = MyBeanFactory.createService();
userService.addUser();
userService.updateUser();
userService.deleteUser();
}
}
测试执行结果