Web程序设计笔记05——第三章:Spring AOP
第三章:Spring AOP
代理:
生活中的代理: 代购(代理对象):卖化妆品 代理 韩国卖化妆品的那个商店(被代理对象):卖化妆品
代理对象和被代理对象的区别?
代理对象可以完成被代理对象的功能,除此之外,代理对象还可以添加额外功能
示例:
package com.gzh;
//韩国商店
public class Shop {
void sell(){
System.out.println("韩国商店卖化妆品100元");
}
}
package com.gzh;
public class Daigou {
private Shop shop;
public void setShop(Shop shop) {
this.shop = shop;
}
void sell(){
System.out.println("代购要收十元小费");
shop.sell();
System.out.println("代购卖化妆品110元");
}
}
package com.gzh;
//Test类模拟买化妆品的人
public class Test {
public static void main(String[] args) {
Daigou daigou = new Daigou();
daigou.setShop(new Shop());
daigou.sell();
}
}
运行截图:
AOP术语
AOP:面向切面编程
(1)Aspect(切面):本质就是类,例如:MyAspect,切面类完成额外功能或非核心业务功能。
(2)Joinpoint(连接点):目标方法的调用的前和后都可以称为连接点,目标方法在被代理类中
(3)pointcut(切入点):就是 切入了额外功能的 连接点
(4)Advice(通知、增强处理):就是额外功能
(5)Target Object(目标对象):被代理对象。例如:com.jdk.UserDaoImpl
(6)Proxy(代理):代理对象
(7)Weaving(织入):产生代理对象的过程,例如;createProxy
3.2.1 JDK动态代理
代理是谁?(或者说被代理对象是谁)?是实现了接口的类:com.jdk.UserDaoImpl
额外功能所在的类? MyAspect类
如何产生代理对象? JdkProxy类
代理对象的额外功能是如何完成的?
package com.jdk;
public interface UserDao {
void addUser();
void deleteUser();
}
package com.jdk;
//被代理对象就是这个实现类,该类中的方法叫做目标方法
public class UserDaoImpl implements UserDao{
@Override
public void addUser() {
System.out.println("添加用户");
}
@Override
public void deleteUser() {
System.out.println("删除用户");
}
}
package com.jdk;
//额外的功能:在目标方法调用前,调用check_permission;在目标方法调用后条用log方法
public class MyAspect {
public void check_permission(){
System.out.println("模拟权限检查");
}
public void log(){
System.out.println("模拟记录日志");
}
}
package com.jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//产生代理对象的类
public class JdkProxy implements InvocationHandler {
private UserDao userDao;
//方法的返回值是代理对象
public Object createProxy(UserDao userDao){
this.userDao=userDao;
ClassLoader classLoader= JdkProxy.class.getClassLoader();
Class[] clazz=userDao.getClass().getInterfaces();
return Proxy.newProxyInstance(classLoader,clazz,this);
}
//invoke方法就是代理对象完成目标功能和额外功能的方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MyAspect myAspect=new MyAspect();
myAspect.check_permission();
Object obj = method.invoke(userDao,args);//当程序指向到此语句时,转而调用目标方法
myAspect.log();
return obj;
}
}
package com.jdk;
public class JdkTest {
public static void main(String[] args) {
//被代理对象
UserDao userDao = new UserDaoImpl();
userDao.addUser();
System.out.println("----------------");
//生成代理对象
JdkProxy jdkProxy = new JdkProxy();
UserDao proxy = (UserDao) jdkProxy.createProxy(userDao);
proxy.addUser();//当程序指向到此语句时,转而执行invoke方法
}
}
运行截图:
3.2.2CGLIB代理
代理是谁?(或者说被代理对象是谁)?User类,有两个目标方法:addUser() deleteUser()
额外功能所在的类? MyAspect类
如何产生代理对象? CglibProxy类中的方法
代理对象的额外功能是如何完成的?
package com.cglib;
public class User {
void addUser() {
System.out.println("添加用户");
}
void deleteUser() {
System.out.println("删除用户");
}
}
package com.cglib;
//额外的功能:在目标方法调用前,调用check_permission;在目标方法调用后条用log方法
public class MyAspect {
public void check_permission() {
System.out.println("模拟权限检查");
}
public void log() {
System.out.println("模拟记录日志");
}
}
package com.cglib;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class Cglibproxy implements MethodInterceptor {
public Object createProxy(Object target) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
MyAspect myAspect = new MyAspect();
myAspect.check_permission();
Object obj = methodProxy.invokeSuper(proxy, args);//程序执行到此条语句时,转而执行目标方法
myAspect.log();
return obj;
}
}
package com.cglib;
public class cglibTest {
public static void main(String[] args) {
//被代理对象
User user = new User();
user.addUser();
System.out.println("---------------");
//代理对象
Cglibproxy cglibProxy = new Cglibproxy();
User proxy = (User) cglibProxy.createProxy(user);
proxy.addUser();//程序执行到此条语句时,转为执行intercept方法
}
}
运行截图如下:
JDK代理和CGLIB代理方式的缺点?
代理对象不管调用哪一种目标方法时,都会调用额外的功能。
能不能有一种手段:可以使得程序员自己自由指定那些目标被调用时,调用额外的功能呢?Spring
License:
CC BY 4.0