AOP术语:包括Aspect(切面)、Joinpoint(连接点)、Pointcut(切入点)、Advice(通知/增强处理)、Target Object(目标对象)、 Proxy(代理)、Weaving(织入)
增强方法的意思就是:调用切面类,将切面类中的方法加到目标类中,扩充其中方法数量,就是增强方法。
例图:
代码:
(1)创建一个web项目,导入Spring框架所需要的JAR包到项目的lib目录下,并发布到类路径下。
(2)在src目录下:创建一个com.itheima.jdk包,在该包下创建接口UserDao ,并在其中编写添加和删除的方法
package com.itheima.jdk;
public interface UserDao {
public void addUser(); //添加
public void deleteUser(); //删除
}
(3)在com.itheima.jdk包中,创建UserDao接口的实现类UserDaoImpl ,分别实现接口中的方法。
package com.itheima.jdk;
import org.springframework.stereotype.Repository;
// 目标类(被代理对象:房主)
@Repository("userDao")
public class UserDaoImpl implements UserDao {
public void addUser() {
System.out.println("添加用户");
}
public void deleteUser() {
System.out.println("删除用户");
}
}
(4)在src目录下,创建一个com.itheima.aspect包,并且在该包下创建切面类MyAspect ,在该类中定义一个模拟权限检查的方法,这两个方法就表示切面中的通知
package com.itheima.aspect;
//切面类:可以存在多个通知Advice(即增强的方法)
public class MyAspect {
public void check_Permissions(){
System.out.println("模拟检查权限...");
}
public void log(){
System.out.println("模拟记录日志...");
}
}
(5)在com.itheima.jdk包下,创建代理类JdkProxy,该类需要实现InvocationHandler接口,并编写代理方法。在代理方法中,需要通过Proxy类实现动态代理
反射:通过对象名/类名,获取class文件,获取该类的所有
通过对象: .getClass ; 通过类名: .class
package com.itheima.jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import com.itheima.aspect.MyAspect;
/**
* JDK代理类
*/
public class JdkProxy implements InvocationHandler{ //InvocationHandler接口实现invoke()方法
// 声明目标类接口(房主)
private UserDao userDao;
// 创建代理方法
public Object createProxy(UserDao userDao) {
this.userDao = userDao;
// 1.类加载器(通过类名反射得到当前类.getClassLoader()再获取类加载器上的容器)
ClassLoader classLoader = JdkProxy.class.getClassLoader();
// 2.被代理对象实现的所有接口,通过userDao对象实例,通过反射getInterfaces获取该类所有方法
Class[] clazz = userDao.getClass().getInterfaces();
// 3.使用代理类,进行增强,返回的是代理后的对象(动态生成一个代理类,参数:一个加载器,userDao的所有方法,该类)
return Proxy.newProxyInstance(classLoader,clazz,this);
}
/*
* 所有动态代理类的方法调用,都会交由invoke()方法去处理
* 执行被代理对象中的方法的反射
* proxy 被代理后的对象
* method 将要被执行的方法信息(反射)
* args 执行方法时需要的参数,几个方法
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// 声明切面
MyAspect myAspect = new MyAspect();
// 前增强
myAspect.check_Permissions();
// 在目标类上调用方法,并传入参数
Object obj = method.invoke(userDao, args);
// 后增强
myAspect.log();
return obj;
}
}
(6)在com.itheima.jdk包下,创建测试类JdkTest,在该类中的main方法中创建代理对象和目标对象,然后从代理对象中获取目标对象userDao增强后的对象,最后调用该对象的添加个删除方法
package com.itheima.jdk;
public class JdkTest{
public static void main(String[] args) {
// 创建代理对象
JdkProxy jdkProxy = new JdkProxy();
// 创建目标对象
UserDao userDao= new UserDaoImpl();
// 从代理对象中获取增强后的目标对象
UserDao userDao1 = (UserDao) jdkProxy.createProxy(userDao);
// 执行方法
userDao1.addUser();
userDao1.deleteUser();
}
}
(1)同上UserDao目标类一样:
package com.itheima.cglib;
//目标类
public class UserDao {
public void addUser() {
System.out.println("添加用户");
}
public void deleteUser() {
System.out.println("删除用户");
}
}
(2)在com.itheima.cglib包中,创建代理类CglibProxy ,该代理类需要实现MethodInterceptor接口,并实现接口中的intercept()方法
package com.itheima.cglib;
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import com.itheima.aspect.MyAspect;
// 代理类
public class CglibProxy implements MethodInterceptor{
// 代理方法
public Object createProxy(Object target) {
// 创建一个动态类对象
Enhancer enhancer = new Enhancer();
// 确定需要增强的类,设置其父类
enhancer.setSuperclass(target.getClass());
// 添加回调函数(自己调用自己)
enhancer.setCallback(this); //this代表的就是代理类CglibProxy 本身
// 返回创建的代理类
return enhancer.create();
}
/**
* proxy CGlib根据指定父类生成的代理对象
* method 拦截的方法
* args 拦截方法的参数数组
* methodProxy 方法的代理对象,用于执行父类的方法
*/
@Override
public Object intercept(Object proxy, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
// 创建切面类对象
MyAspect myAspect = new MyAspect();
// 前增强
myAspect.check_Permissions();
// 目标方法执行
Object obj = methodProxy.invokeSuper(proxy, args);
// 后增强
myAspect.log();
return obj;
}
}
(3)在com.itheima.cglib包中,创建测试类CglibTest 。
package com.itheima.cglib;
// 测试类
public class CglibTest {
public static void main(String[] args) {
// 创建代理对象
CglibProxy cglibProxy = new CglibProxy();
// 创建目标对象
UserDao userDao = new UserDao();
// 获取增强后的目标对象
UserDao userDao1 = (UserDao)cglibProxy.createProxy(userDao);
// 执行方法
userDao1.addUser();
userDao1.deleteUser();
}
}