当需要在方法前后做一些操作就需要借助动态代理来实现
jdk实现代理是被代理类实现接口的方式
public interface UserInterface {
void test();
}
public class UserService implements UserInterface {
public void test() {
System.out.println("call test method");
}
}
UserService target = new UserService();
Object o = Proxy.newProxyInstance(Test.class.getClassLoader(), new Class[]{UserInterface.class}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("test method before");
Object invoke = method.invoke(target, args);
System.out.println("test method after");
return invoke;
}
});
// 只能代理实现UserInterface接口的类,不能强转成UserService
UserInterface userInterface = (UserInterface)o;
userInterface.test();
打印结果:
test method before
call test method
test method after
必须基于实现接口,产生代理对象类型是UserInterface,而不是UserService
相比jdk动态代理,cglib不需要修改代码就可以实现动态代理,cglib实现代理是继承被代理类的方式
public class UserService {
public void test() {
System.out.println("call test method");
}
public void a() {
System.out.println("call test a");
}
}
UserService target = new UserService();
// 通过cglib技术
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(UserService.class);
// 定义额外逻辑,也就是代理逻辑
enhancer.setCallbacks(new Callback[]{new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("before...");
Object result = methodProxy.invoke(target, objects);
System.out.println("after...");
return result;
}
}, NoOp.INSTANCE});
enhancer.setCallbackFilter(new CallbackFilter() {
@Override
public int accept(Method method) {
if (method.getName().equals("test")) {
return 0;
} else {
return 1;
}
}
});
// 动态代理所创建出来的UserService对象
UserService userService = (UserService) enhancer.create();
// 执行这个userService的test方法时,就会额外会执行一些其他逻辑
userService.test();
// 调用a方法时对应过滤返回的是1,NoOp.INSTANCE是空操作,不会对代理对象做任何操作
userService.a();
打印结果:
before...
call test method
after...
call test a
public class UserService {
public void test() {
System.out.println("call test method");
}
}
UserService target = new UserService();
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(target);
// proxyFactory.setInterfaces(UserInterface.class); // jdk动态时设置
proxyFactory.addAdvice(new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("before...");
Object result = invocation.proceed();
System.out.println("after...");
return result;
}
});
UserService userService = (UserService) proxyFactory.getProxy();
userService.test();
打印结果:
before...
call test method
after...
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(target);
// proxyFactory.setInterfaces(UserInterface.class); // jdk动态时设置
proxyFactory.addAdvice(new TestBeforeAdvice());
UserService userService = (UserService) proxyFactory.getProxy();
userService.test();
public class TestBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("方法执行之前");
}
}
public class UserService {
public void test() {
System.out.println("call test method");
}
}
打印结果:
方法执行之前
call test method
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(target);
// proxyFactory.setInterfaces(UserInterface.class); // jdk动态时设置
proxyFactory.addAdvice(new TestAfterReturningAdvice());
UserService userService = (UserService) proxyFactory.getProxy();
userService.test();
public class TestAfterReturningAdvice implements AfterReturningAdvice {
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("方法返回之后");
}
}
public class UserService {
public void test() {
System.out.println("call test method");
}
}
打印结果:
call test method
方法返回之后
可根据异常类型在指定异常发生时做对应操作
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(target);
// proxyFactory.setInterfaces(UserInterface.class); // jdk动态时设置
proxyFactory.addAdvice(new TestAfterThrowingAdvice());
UserService userService = (UserService) proxyFactory.getProxy();
userService.test();
public class TestAfterThrowingAdvice implements ThrowsAdvice {
public void afterThrowing(Method method, Object[] args, Object target, Exception ex) {
System.out.println("方法执行发生异常");
}
}
public class UserService {
public void test() {
System.out.println("call test method");
throw new RuntimeException();
}
}
打印结果:
call test method
方法执行发生异常
Exception in thread "main" java.lang.RuntimeException
at com.zhouyu.service.UserService.test(UserService.java:25)
at com.zhouyu.service.UserService$$FastClassBySpringCGLIB$$7bfcfe0.invoke()
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:791)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:166)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:762)
at org.springframework.aop.framework.adapter.ThrowsAdviceInterceptor.invoke(ThrowsAdviceInterceptor.java:113)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:198)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:762)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:704)
at com.zhouyu.service.UserService$$EnhancerBySpringCGLIB$$e9a0fc71.test()
at com.zhouyu.Test.main(Test.java:25)
UserService target = new UserService();
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(target);
// proxyFactory.setInterfaces(UserInterface.class); // jdk动态时设置
proxyFactory.addAdvice(new TestAroundAdvice());
UserService userService = (UserService) proxyFactory.getProxy();
userService.test();
public class UserService {
public void test() {
System.out.println("call test method");
}
}
public class TestAroundAdvice implements MethodInterceptor {
@Nullable
@Override
public Object invoke(@NotNull MethodInvocation invocation) throws Throwable {
System.out.println("方法执行之前");
Object proceed = invocation.proceed();
System.out.println("方法执行之后");
return proceed;
}
}
打印结果:
方法执行之前
call test method
方法执行之后
上述的Advice只要是UserService类的方法都会被代理执行
添加自己想执行的执行的方法,下面代码只会执行test方法的Advice代码
public class UserService {
public void test() {
System.out.println("call test method");
}
public void a() {
System.out.println("call test a");
}
}
UserService target = new UserService();
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(target);
// proxyFactory.setInterfaces(UserInterface.class); // jdk动态时设置
// proxyFactory.addAdvice(new TestBeforeAdvice());
proxyFactory.addAdvisor(new PointcutAdvisor() {
@Override
public Pointcut getPointcut() {
return new StaticMethodMatcherPointcut() {
@Override
public boolean matches(Method method, Class> targetClass) {
if (method.getName().equals("test")) {
return true;
}
return false;
}
};
}
@Override
public Advice getAdvice() {
return new TestBeforeAdvice();
}
@Override
public boolean isPerInstance() {
return false;
}
});
UserService userService = (UserService) proxyFactory.getProxy();
userService.test();
userService.a();
打印结果:
方法执行之前
call test method
call test a
利用ProxyFactoryBean生成一个代理对象,执行test方法之前执行代理逻辑
public class UserService {
public void test() {
System.out.println("call test method");
}
public void a() {
System.out.println("call test a");
}
}
@Bean
public ProxyFactoryBean userServiceProxy() {
ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();
proxyFactoryBean.setTarget(new UserService());
proxyFactoryBean.addAdvice(new TestBeforeAdvice());
return proxyFactoryBean;
}
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = (UserService) applicationContext.getBean("userServiceProxy");
userService.test();
打印结果:
方法执行之前
call test method
beanName匹配到的将会自动创建代理对象,根据设置的Advice在调用方法时执行相关代理逻辑(通过beanPostProcessor把Advice添加到一个集合中,当调用调用被代理类时,指定的beanName的方法执行时都会执行代理逻辑)
@Bean
public BeanNameAutoProxyCreator beanNameAutoProxyCreator() {
BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator();
beanNameAutoProxyCreator.setBeanNames("userSe*");
beanNameAutoProxyCreator.setInterceptorNames("testBeforeAdvice");
beanNameAutoProxyCreator.setProxyTargetClass(true);
return beanNameAutoProxyCreator;
}
@Component
public class TestBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("方法执行之前");
}
}
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = (UserService) applicationContext.getBean("userService");
userService.test();
打印结果:
方法执行之前
call test method
// 定义一个advisor
@Bean
public DefaultPointcutAdvisor defaultPointcutAdvisor(){
NameMatchMethodPointcut pointcut = new NameMatchMethodPointcut();
pointcut.addMethodName("test");
DefaultPointcutAdvisor defaultPointcutAdvisor = new DefaultPointcutAdvisor();
defaultPointcutAdvisor.setPointcut(pointcut);
defaultPointcutAdvisor.setAdvice(new TestBeforeAdvice());
return defaultPointcutAdvisor;
}
// 执行beanPostProcessor时会把advisor添加到一个集合中
@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
return defaultAdvisorAutoProxyCreator;
}
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = (UserService) applicationContext.getBean("userService");
userService.test();
打印结果:
方法执行之前
call test method
AspectJ是在编译时对字节码进行了修改,是直接在UserService类对应的字节码中进行增强的,也就是可以理解为是在编译时就会去解析@Before这些注解,然后得到代理逻辑,加入到被代理的类中的字节码中去的,所以如果想用AspectJ技术来生成代理对象 ,是需要用单独的AspectJ编译器的。我们在项目中很少这么用,我们仅仅只是用了@Before这些注解,而我们在启动Spring的过程中,Spring会去解析这些注解,然后利用动态代理机制生成代理对象的。
AspectJ定义的几个注解