版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hlw521hxq/article/details/82989850
实现方法:动态代理设计模式
-
JDK 的动态代理:针对实现了接口的类产生代理。InvocationHandler接口
-
CGlib 的动态代理:针对没有实现接口的类产生代理,应用的是底层的字节码增强的技术 生成当前类的子类对象,MethodInterceptor接口
JDK动态代理
-
创建接口和实现类
-
创建代理类,实现InvocationHandler接口
//创建被代理对象 private UserDao dao; public Agency(UserDao dao){ this.dao=dao; } //创建代理对象 public UserDao CreatAgency(){ // Proxy.newProxyInstance(类的加载器,对象实现的接口,调用者) UserDao userdao = (UserDao)Proxy.newProxyInstance(dao.getClass().getClassLoader(), dao.getClass().getInterfaces(), this); return userdao; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("一切之初"); Object om = method.invoke(dao, args); System.out.println("终焉"); return om; }
-
测试
//获取代理对象 *//* UserDao u = new U();*//* //创建代理类对象 Agency agency = new Agency(u); //创建代理对象 UserDao um = agency.CreatAgency(); //调用方法 um.sing();
CGlib动态代理
实现接口MethodInterceptor,来自import org.springframework.cglib.proxy.MethodInterceptor;不要错误了
-
创建普通类:方法
-
创建代理器,实现MethodInterceptor接口
代码与上一个相同,区别的地方时创建代理对象的方法
//创建代理对象的方法 public UsersDaoImpl createdaili(){ Enhancer en=new Enhancer();//创建核心类 en.setSuperclass(user.getClass());//为其设置父类 en.setCallback(this);//设置回调 return (UsersDaoImpl)en.create(); } public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { 执行方法之前语句块 Object o1 = methodProxy.invokeSuper(o, objects); 执行方法之后语句块 return o1; }
-
测试:与JDK动态代理测试方法一致
AOP实现:以上两种方式代码自动判断实现
-
添加jar包
-
创建Aop增强类(本质普通类)
-
前置通知
-
返回通知
-
后置异常通知
-
后置最终通知
-
环绕通知:有返回值,必须返回,否则报错
-
public Object around(ProceedingJoinPoint point) throws Throwable{}
-
xml文件添加命名空间aop
xmlns:aop="http://www.springframework.org/schema/aop" http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
-
设置配置文件
<!--创建目标类对象--> <bean name="userService" class="com.itqf.spring.service.UserServiceImpl" /> <!--配置增强类对象--> <bean name="myAdvice" class="com.itqf.spring.aop.MyAdivce" /> <!-- 配置将增强织入目标对象--> <aop:config> <aop:pointcut id="pc" expression="execution(* com.itqf.spring.service.*ServiceImpl.*(..))"/> <aop:aspect ref="myAdvice"> <aop:before method="before" pointcut-ref="pc" /> <aop:after-returning method="afterReturning" pointcut-ref="pc" /> <aop:around method="around" pointcut-ref="pc" /> <aop:after-throwing method="afterException" pointcut-ref="pc" /> <aop:after method="after" pointcut-ref="pc" /> </aop:aspect> </aop:config> 注意:(1)环绕增强需要使用ProceedingJoinPoint 作为参数(2)注意标签顺序
-
切入点匹配规则:
public * addUser(com.pb.entity.User):“*”表示匹配所有类型的返回值。 示例:public int addUser(User u); public String addUser(User u); public void *(com.pb.entity.User):“*”表示匹配所有方法名。 示例:public void selectUser(User u); public void a(User u); public void addUser (..):“..”表示匹配所有参数个数和类型。 示例: public void addUser(int a) public void addUser(int b,int c) * com.pb.service.*.*(..):匹配com.pb.service 包下所有类的所有方法。 示例: public void com.pb.service.A.a(); public String com.pb.service.B.a(); * com.pb.service..*(..):匹配com.pb.service 包及子包下所有类的所有方法
获取切入点信息
通过aop类,添加参数JoinPoint对象获取信息
"切入点对象:"+jp.getTarget().getClass().getSimpleName(); "切入点方法:"+jp.getSignature(); "切入点的参数:"+jp.getArgs()[0];
特殊增强——Advisor前置增强实现步骤
-
创建增强类,实现MethodBeforeAdvice接口
-
在配置文件,aop配置切入点后,加入
<aop:advisor advice-ref="增强类对象的id" pointcut-ref="切入点对象的id"/>
注解实现Aop
-
启动aspectj注解
<aop:aspectj-autoproxy/>
-
在切面类上添加@Aspect
-
定义切面方法(任意),添加切入点注解@Pointcut(“execution(切入路径)”)
-
@Before 前置 @After 最终 @Around 环绕 @AfterReturning 后置 @AfterThrowing 异常
eg: @Before("切入方法()")