一,动态代理
概念:动态代理是一种非常重要的技术,它允许在运行时动态地创建代理对象,以便于在代理对象中添加一些额外的功能。动态代理可以分为两种:JDK动态代理和CGLIB动态代理。JDK动态代理是基于Java反射机制实现的,只能代理接口类型的类;而CGLIB动态代理则是基于字节码技术实现的,可以代理普通的类。
示例:
假设我们有一个接口UserService
和一个实现类UserServiceImpl
,现在我们需要在每次调用UserService
的方法时记录日志。我们可以通过动态代理来实现这个功能。
1,首先,我们需要定义一个代理类UserServiceProxy
,并实现InvocationHandler
接口
public class UserServiceProxy implements InvocationHandler {
private Object target;
public UserServiceProxy(Object target)
{ this.target = target; }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("调用方法:" + method.getName());
Object result = method.invoke(target, args);
System.out.println("方法调用结束"); return result;
}
}
2,然后,在UserService
接口中添加一个方法getProxy()
,用于创建代理对象
public interface UserService {
void addUser(String name);
void deleteUser(String name);
Object getProxy();
}
3,在UserServiceImpl
实现类中,实现getProxy()
方法,创建代理对象
public class UserServiceImpl implements UserService {
@Override
public void addUser(String name) {
System.out.println("添加用户:" + name);
}
@Override public void deleteUser(String name) {
System.out.println("删除用户:" + name);
}
@Override public Object getProxy() {
return Proxy.newProxyInstance(UserServiceImpl.class.getClassLoader(), UserServiceImpl.class.getInterfaces(), new UserServiceProxy(this));
}
}
4,最后,在测试代码中,调用getProxy()
方法来获取代理对象,然后调用addUser()
和deleteUser()
方法
public class Test {
public static void main(String[] args) {
UserService userService = new UserServiceImpl().getProxy();
userService.addUser("张三");
userService.deleteUser("张三");
}
}
可以看到,每次调用UserService
接口的方法时,都会先输出方法名称,然后调用实际的方法,最后输出方法调用结束的信息。
二,AOP
概念:在Spring框架中,AOP是一个重要的功能模块,它提供了一种方便的方式来实现横切关注点的处理。Spring AOP基于代理模式实现,通过动态代理技术,可以在不修改原有代码的情况下,将横切关注点与核心业务逻辑进行分离。
Spring AOP中的概念:
-
切面(Aspect):横切关注点的实现,是一个类,其中包含了通知和切点。
-
通知(Advice):切面中的具体逻辑实现,如前置通知、后置通知、环绕通知等。
-
切点(Pointcut):定义了哪些类、方法需要被切入,通常使用表达式进行定义。
-
连接点(Joinpoint):程序执行过程中的一个点,如方法调用、异常处理等。
-
织入(Weaving):将切面应用到目标对象上的过程。
示例:
1,创建一个BookService接口
package com.smrsar.service;
public interface BookService {
void findAll();
int add();
void del(int id);
void update();
}
2,创建BookService的实现类
package com.smrsar.service.impl;
import com.smrsar.service.BookService;
public class BookServiceImpl implements BookService {
@Override
public void findAll() {
System.out.println("全查");
}
@Override
public int add() {
System.out.println("添加");
return 0;
}
@Override
public void del(int id) {
System.out.println("删除");
}
@Override
public void update() {
System.out.println("修改");
}
}
3,创建通知/增强类
package com.smrsar.log;
public class Loggs {
public void before(){
System.out.println("前置通知/增强:权限验证");
}
public void afterReturning(){
System.out.println("后置通知/增强:日志输出");
}
public void afterThrowing(){
System.out.println("异常通知/增强:异常处理");
}
public void after(){
System.out.println("最终通知/增强:资源释放");
}
}
4,创建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
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--1.把所有类的对象交给IOC容器进行管理-->
<bean id="loggs" class="com.smrsar.log.Loggs"/>
<bean id="bookService" class="com.smrsar.service.impl.BookServiceImpl"/>
<!--2.AOP的配置:让增强类 的 哪个方法 动态进行何种增强 核心类 的 哪个方法-->
<aop:config>
<aop:aspect id="check" ref="loggs">
<aop:before method="before" pointcut="execution(* *..BookServiceImpl.*(..))"/>
<aop:after-returning method="afterReturning" pointcut="execution(* *..BookServiceImpl.*(..))"/>
<aop:after-throwing method="afterThrowing" pointcut="execution(* *..BookServiceImpl.*(..))"/>
<aop:after method="after" pointcut="execution(* *..BookServiceImpl.*(..))"/>
</aop:aspect>
</aop:config>
</beans>
5,测试
package com.smrsar.servlet;
import com.smrsar.service.BookService;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test01 {
public static void main(String[] args) {
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
BookService bookService = context.getBean(BookService.class);
bookService.findAll();
}
}
6,输出结果
前置通知/增强:权限验证
全查
后置通知/增强:日志输出
最终通知/增强:资源释放
总结:Spring框架中的AOP功能就是基于动态代理实现的,通过使用切面、通知、切点等概念,来实现对目标对象的增强。AOP用于实现在不修改原有代码的情况下,增强程序的功能。