1.项目初始化
1.1 pom.xml
<dependencies><!-- spring依赖 --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.5.RELEASE</version></dependency><!-- spring事务依赖 --><dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId><version>5.2.5.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.2.5.RELEASE</version></dependency><!-- mybatis依赖 --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.1</version></dependency><!-- mybatis和spring集成依赖 --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>1.3.1</version></dependency><!-- mysql驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.9</version></dependency><!-- 阿里的连接池 --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.12</version></dependency><!-- aspectj--><dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId><version>1.9.5</version></dependency><dependency><groupId>org.apache.geronimo.bundles</groupId><artifactId>aspectjweaver</artifactId><version>1.6.8_2</version></dependency></dependencies>
1.2UserService对象
package com.nq.service;import org.springframework.stereotype.Component;/*** @author Nickel* @version 1.0* @date 2023/7/29 23:04*/
@Component
public class UserService {public void test(){System.out.println("test方法。");}public void a(){System.out.println("a方法。");}
}
2.cjlib动态代理的使用
2.1所有的方法都是使用动态代理
package com.nq.service;import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;import java.lang.reflect.Method;/*** @author Nickel* @version 1.0* @date 2023/7/29 23:29*/
public class CglibTest {public static void main(String[] args) {UserService target =new UserService();Enhancer enhancer=new Enhancer();enhancer.setSuperclass(UserService.class);enhancer.setCallbacks(new Callback[]{new MethodInterceptor() {@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("before...");//被代理的对象,目标方法//Object result=methodProxy.invoke(target,objects);//Object result=method.invoke(target,objects);Object result=methodProxy.invokeSuper(o,objects);System.out.println("After...");return result;}}});UserService userService = (UserService) enhancer.create();userService.test();}
}
2.2不同的方法使用不同的代理
package com.nq.service;import org.springframework.cglib.proxy.*;import java.lang.reflect.Method;/*** @author Nickel* @version 1.0* @date 2023/7/29 23:29*/
public class CglibTest {public static void main(String[] args) {UserService target =new UserService();Enhancer enhancer=new Enhancer();enhancer.setSuperclass(UserService.class);enhancer.setCallbacks(new Callback[]{new MethodInterceptor() {@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("before...");//被代理的对象,目标方法//Object result=methodProxy.invoke(target,objects);//Object result=method.invoke(target,objects);Object result=methodProxy.invokeSuper(o,objects);System.out.println("After...");return result;}}, NoOp.INSTANCE});enhancer.setCallbackFilter(new CallbackFilter() {@Overridepublic int accept(Method method) {if("test".equals(method.getName())){//表示test方法执行第一个代理方法,其他方法执行第二个方法return 0;}else{return 1;}}});UserService userService = (UserService) enhancer.create();userService.a();}
}
3.jdk动态代理的使用
3.1UserInterface创建接口
package com.nq.service;/*** @author Nickel* @version 1.0* @date 2023/7/29 23:58*/
public interface UserInterface {void test();void a();
}
3.2UserService实现接口
package com.nq.service;import org.springframework.stereotype.Component;/*** @author Nickel* @version 1.0* @date 2023/7/29 23:04*/
@Component
public class UserService implements UserInterface{public void test(){System.out.println("test方法。");}public void a(){System.out.println("a方法。");}
}
3.3JdkTest代理的main方法
package com.nq.service;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;/*** @author Nickel* @version 1.0* @date 2023/7/29 23:56*/
public class JdkTest {public static void main(String[] args) {UserInterface target=new UserService();UserInterface userInterface =(UserInterface) Proxy.newProxyInstance(JdkTest.class.getClassLoader(), new Class[]{UserInterface.class}, new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("Jdk动态代理被执行了,方法之前");method.invoke(target,args);System.out.println("Jdk动态代理被执行了,方法之后");return null;}});userInterface.test();}
}
4.spring中动态代理的使用
4.1proxyFactory 动态代理的使用方法
NickelBeforeAdvice.java方法执行之前
package com.nq.advice;import org.springframework.aop.BeforeAdvice;
import org.springframework.aop.MethodBeforeAdvice;import java.lang.reflect.Method;/*** @author Nickel* @version 1.0* @date 2023/7/30 0:59*/
public class NickelBeforeAdvice implements MethodBeforeAdvice {@Overridepublic void before(Method method, Object[] objects, Object o) throws Throwable {System.out.println("方法执行前被执行了");}
}
NickelAfterReturningAdvice.java方法执行之后
package com.nq.advice;import org.aspectj.lang.annotation.AfterReturning;
import org.springframework.aop.AfterReturningAdvice;import java.lang.reflect.Method;/*** @author Nickel* @version 1.0* @date 2023/7/30 0:59*/
public class NickelAfterReturningAdvice implements AfterReturningAdvice {@Overridepublic void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {System.out.println("方法returning被执行了");}
}
NickelAroundadvice.java环绕方法
package com.nq.advice;import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;/*** @author Nickel* @version 1.0* @date 2023/7/30 0:59*/
public class NickelAroundadvice implements MethodInterceptor {@Overridepublic Object invoke(MethodInvocation invocation) throws Throwable {System.out.println("方法执行round之前");Object proceed = invocation.proceed();System.out.println("方法执行round之后");return proceed;}
}
NickelThrowAdvice.java抛异常方法
package com.nq.advice;import org.springframework.aop.ThrowsAdvice;import java.lang.reflect.Method;/*** @author Nickel* @version 1.0* @date 2023/7/30 1:00*/
public class NickelThrowAdvice implements ThrowsAdvice {public void afterThrowing(Method method, Object[] args, Object target, NullPointerException ex) {System.out.println("方法抛异常执行了");}
}
UserService.java抛异常方法
package com.nq.service;import org.springframework.stereotype.Component;/*** @author Nickel* @version 1.0* @date 2023/7/29 23:04*/
@Component
public class UserService implements UserInterface{public void test(){System.out.println("test方法。");}public void a(){System.out.println("a方法。");throw new NullPointerException();}
}
SpringProxtFactoryTest.java测试方法
package com.nq.service;import com.nq.advice.NickelAfterReturningAdvice;
import com.nq.advice.NickelAroundadvice;
import com.nq.advice.NickelBeforeAdvice;
import com.nq.advice.NickelThrowAdvice;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.framework.ProxyFactory;import java.lang.reflect.Method;/*** @author Nickel* @version 1.0* @date 2023/7/30 0:49*/
public class SpringProxtFactoryTest {public static void main(String[] args) {UserService target=new UserService();ProxyFactory proxyFactory=new ProxyFactory();proxyFactory.setTarget(target);//proxyFactory.setInterfaces(UserInterface.class);这里可以指定为接口类型proxyFactory.addAdvice(new NickelAroundadvice());proxyFactory.addAdvice(new NickelBeforeAdvice());UserService userService = (UserService) proxyFactory.getProxy();userService.test();}
}
4.2proxyFactory 对方法名字进行限制
NickelStaticMethodMatherPointcut.java方法匹配的方法
package com.nq.advice;import org.springframework.aop.support.StaticMethodMatcherPointcut;import java.lang.reflect.Method;/*** @author Nickel* @version 1.0* @date 2023/7/30 1:39*/
public class NickelStaticMethodMatherPointcut extends StaticMethodMatcherPointcut {@Overridepublic boolean matches(Method method, Class<?> aClass) {return method.getName().equals("test");}
}
NickelPointcutAdvisor.java切面方法
package com.nq.advice;import org.aopalliance.aop.Advice;
import org.springframework.aop.Pointcut;
import org.springframework.aop.PointcutAdvisor;
import org.springframework.aop.support.StaticMethodMatcherPointcut;import java.lang.reflect.Method;/*** @author Nickel* @version 1.0* @date 2023/7/30 1:34*/
public class NickelPointcutAdvisor implements PointcutAdvisor {@Overridepublic Pointcut getPointcut() {return new NickelStaticMethodMatherPointcut();}@Overridepublic Advice getAdvice() {return new NickelBeforeAdvice();}@Overridepublic boolean isPerInstance() {return false;}
}
SpringProxtFactoryTest.java测试的方法
package com.nq.service;import com.nq.advice.*;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.framework.ProxyFactory;import java.lang.reflect.Method;/*** @author Nickel* @version 1.0* @date 2023/7/30 0:49*/
public class SpringProxtFactoryTest {public static void main(String[] args) {UserService target=new UserService();ProxyFactory proxyFactory=new ProxyFactory();proxyFactory.setTarget(target);//proxyFactory.setInterfaces(UserInterface.class);这里可以指定为接口类型//proxyFactory.addAdvice(new NickelAroundadvice());//proxyFactory.addAdvice(new NickelBeforeAdvice());proxyFactory.addAdvisor(new NickelPointcutAdvisor());UserService userService = (UserService) proxyFactory.getProxy();userService.test();}
}
4.3spring中的动态代理方式
4.3.1spring执行方法时候启动逻辑
UserService.java修改
package com.nq.service;import org.springframework.stereotype.Component;/*** @author Nickel* @version 1.0* @date 2023/7/29 23:04*/
public class UserService{public void test(){System.out.println("test方法。");}public void a(){System.out.println("a方法。");//throw new NullPointerException();}
}
说明:这里需要去掉Component注解
AppConfig.java配置
package com.nq.service;import com.nq.advice.NickelAfterReturningAdvice;
import com.nq.advice.NickelBeforeAdvice;
import org.springframework.aop.framework.ProxyFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;/*** @author Nickel* @version 1.0* @date 2023/7/28 14:59*/
@ComponentScan("com.nq")
public class AppConfig {@Beanpublic ProxyFactoryBean userService(){UserService userService=new UserService();ProxyFactoryBean proxyFactoryBean=new ProxyFactoryBean();proxyFactoryBean.addAdvice(new NickelAfterReturningAdvice());proxyFactoryBean.setTarget(userService);return proxyFactoryBean;}}
Test.java配置
package com.nq.service;import org.springframework.context.annotation.AnnotationConfigApplicationContext;/*** @author Nickel* @version 1.0* @date 2023/7/29 23:00*/public class Test {public static void main(String[] args) {AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext();context.register(AppConfig.class);context.refresh();UserService userService = (UserService) context.getBean("userService");userService.test();}
}
启动Test.java显示结果
4.3.2不去掉注解,spring执行方法的时候执行对应的逻辑
修改NickelAfterReturningAdvice.Java,增加注解
package com.nq.advice;import org.aspectj.lang.annotation.AfterReturning;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.stereotype.Component;import java.lang.reflect.Method;/*** @author Nickel* @version 1.0* @date 2023/7/30 0:59*/
@Component
public class NickelAfterReturningAdvice implements AfterReturningAdvice {@Overridepublic void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {System.out.println("方法returning被执行了");}
}
修改UserService.Java,增加注解
package com.nq.service;import org.springframework.stereotype.Component;/*** @author Nickel* @version 1.0* @date 2023/7/29 23:04*/
@Component
public class UserService{public void test(){System.out.println("test方法。");}public void a(){System.out.println("a方法。");//throw new NullPointerException();}
}
修改AppConfig.Java配置文件
package com.nq.service;import com.nq.advice.NickelAfterReturningAdvice;
import com.nq.advice.NickelBeforeAdvice;
import org.springframework.aop.framework.ProxyFactoryBean;
import org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;/*** @author Nickel* @version 1.0* @date 2023/7/28 14:59*/
@ComponentScan("com.nq")
public class AppConfig {@Beanpublic BeanNameAutoProxyCreator beanNameAutoProxyCreator(){BeanNameAutoProxyCreator beanNameAutoProxyCreator=new BeanNameAutoProxyCreator();beanNameAutoProxyCreator.setBeanNames("userSe*");beanNameAutoProxyCreator.setInterceptorNames("nickelAfterReturningAdvice");beanNameAutoProxyCreator.setProxyTargetClass(true);return beanNameAutoProxyCreator;}}
Test.Java配置文件
package com.nq.service;import org.springframework.context.annotation.AnnotationConfigApplicationContext;/*** @author Nickel* @version 1.0* @date 2023/7/29 23:00*/public class Test {public static void main(String[] args) {AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext();context.register(AppConfig.class);context.refresh();UserService userService = (UserService) context.getBean("userService");userService.test();}
}
Test测试结果
4.3.3AppConfig另外实现动态代理
package com.nq.service;import com.nq.advice.NickelAfterReturningAdvice;
import com.nq.advice.NickelBeforeAdvice;
import org.springframework.aop.framework.DefaultAdvisorChainFactory;
import org.springframework.aop.framework.ProxyFactoryBean;
import org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.NameMatchMethodPointcut;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;/*** @author Nickel* @version 1.0* @date 2023/7/28 14:59*/
@ComponentScan("com.nq")
public class AppConfig {@Beanpublic DefaultPointcutAdvisor defaultPointcutAdvisor(){NameMatchMethodPointcut pointcut=new NameMatchMethodPointcut();pointcut.addMethodName("test");DefaultPointcutAdvisor defaultPointcutAdvisor=new DefaultPointcutAdvisor();defaultPointcutAdvisor.setPointcut(pointcut);defaultPointcutAdvisor.setAdvice(new NickelAfterReturningAdvice());return defaultPointcutAdvisor;}@Beanpublic DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator=new DefaultAdvisorAutoProxyCreator();return defaultAdvisorAutoProxyCreator;}}
测试结果
其中DefaultAdvisorAutoProxyCreator通过导入的方式
package com.nq.service;import com.nq.advice.NickelAfterReturningAdvice;
import com.nq.advice.NickelBeforeAdvice;
import org.springframework.aop.framework.DefaultAdvisorChainFactory;
import org.springframework.aop.framework.ProxyFactoryBean;
import org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.NameMatchMethodPointcut;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;/*** @author Nickel* @version 1.0* @date 2023/7/28 14:59*/
@ComponentScan("com.nq")
@Import(DefaultAdvisorAutoProxyCreator.class)
public class AppConfig {@Beanpublic DefaultPointcutAdvisor defaultPointcutAdvisor(){NameMatchMethodPointcut pointcut=new NameMatchMethodPointcut();pointcut.addMethodName("test");DefaultPointcutAdvisor defaultPointcutAdvisor=new DefaultPointcutAdvisor();defaultPointcutAdvisor.setPointcut(pointcut);defaultPointcutAdvisor.setAdvice(new NickelAfterReturningAdvice());return defaultPointcutAdvisor;}
}
4.4spring中Aspect的使用
创建NickelAspect.java
package com.nq.aspect;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;/*** @author Nickel* @version 1.0* @date 2023/7/30 2:37*/
@Aspect
@Component
public class NickelAspect {@Before("execution(public void com.nq.service.UserService.test())")public void nickelBefore(JoinPoint joinPoint){System.out.println("NickelAspect执行了");}
}
修改AppConfig.java扫描类
package com.nq.service;import com.nq.advice.NickelAfterReturningAdvice;
import com.nq.advice.NickelBeforeAdvice;
import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator;
import org.springframework.aop.framework.DefaultAdvisorChainFactory;
import org.springframework.aop.framework.ProxyFactoryBean;
import org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.NameMatchMethodPointcut;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.Import;/*** @author Nickel* @version 1.0* @date 2023/7/28 14:59*/
@ComponentScan("com.nq")
@Import(AnnotationAwareAspectJAutoProxyCreator.class)
//@EnableAspectJAutoProxy
public class AppConfig {}
启动测试类测试