代理模式:为其他对象提供一种代理以控制对这个对象的访问,增强一个类中的某个方法,对程序进行扩展。
动态代理可以在不修改类源码的前提下,给类中方法增加额外逻辑
通过cglib来实现的代理对象的创建:
基于父子类,被代理类是父类,代理类是子类,代理对象就是代理类的实例对象,代理类是由cglib创建的
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;
// cglib动态代理单独使用
public class Test
{
public static void main(String[] args)
{
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);
// // 写法二
// Object result = method.invoke(target, objects);
// 写法三
Object result = methodProxy.invokeSuper(o, objects);
System.out.println("after...");
return result;
}
}});
// 动态代理所创建出来的UserService对象
UserService userService = (UserService)enhancer.create();
// 执行这个userService的test方法时,就会额外会执行一些其他逻辑
userService.test();
}
}
public class UserService
{
public void test()
{
System.out.println("test");
}
}
利用JDK动态代理来生成一个代理对象:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Test
{
public static void main(String[] args)
{
UserService target = new UserService();
// UserInterface接口的代理对象
Object proxy = Proxy.newProxyInstance(UserService.class.getClassLoader(),
new Class[] {UserInterface.class}, new InvocationHandler()
{
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable
{
System.out.println("before...");
Object result = method.invoke(target, args);
System.out.println("after...");
return result;
}
});
// 注意这里必须是接口类型UserInterface,如果是UserService类会报错
UserInterface userService = (UserInterface)proxy;
userService.test();
}
}
public class UserService implements UserInterface
{
@Override
public void test()
{
System.out.println("test");
}
}
public interface UserInterface
{
public void test();
}
注意:代理对象proxy必须是接口类型
Spring对上面的两种动态代理技术进行了封装,封装出来的类叫做ProxyFactory
表示创建代理对象的一个工厂,使用起来更加方便
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.framework.ProxyFactory;
public class Test
{
public static void main(String[] args)
{
UserService target = new UserService();
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(target);
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;
}
});
UserInterface userService = (UserInterface)proxyFactory.getProxy();
userService.test();
}
}
public class UserService implements UserInterface
{
@Override
public void test()
{
System.out.println("test");
}
}
public interface UserInterface
{
public void test();
}
ProxyFactory会自动判断是用cglib还是jdk动态代理
如果类实现了接口,那么ProxyFactory底层就会用jdk动态代理
如果没有实现接口,就会用cglib技术
1、Before Advice:方法之前执行
2、After returning advice:方法return后执行
3、After throwing advice:方法抛异常后执行
4、After (finally) advice:方法执行完finally之后执行,这是最后的,比return更后
5、Around advice:这是功能最强大的Advice,可以自定义执行顺序
一个Advisor是有一个Pointcut和一个Advice组成的,通过Pointcut可以指定需要被代理的逻辑
可以通过Advisor来控制具体代理哪个方法
public class Test
{
public static void main(String[] args)
{
UserService target = new UserService();
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(target);
proxyFactory.addAdvisor(new PointcutAdvisor()
{
@Override
public Pointcut getPointcut()
{
return new StaticMethodMatcherPointcut()
{
@Override
public boolean matches(Method method, Class> targetClass)
{
return method.getName().equals("testAbc");
}
};
}
@Override
public Advice getAdvice()
{
return new MethodInterceptor()
{
@Override
public Object invoke(MethodInvocation invocation)
throws Throwable
{
System.out.println("before...");
Object result = invocation.proceed();
System.out.println("after...");
return result;
}
};
}
@Override
public boolean isPerInstance()
{
return false;
}
});
UserInterface userService = (UserInterface)proxyFactory.getProxy();
userService.test();
}
}
public class UserService
{
public void test()
{
System.out.println("test");
}
}
@ComponentScan(value = "com.gax")
public class AppConfig
{
@Bean
public ProxyFactoryBean userService()
{
UserService userService = new UserService();
ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();
proxyFactoryBean.setTarget(userService);
proxyFactoryBean.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;
}
});
return proxyFactoryBean;
}
}
public class Test
{
public static void main(String[] args)
{
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userServiceProxy = (UserService)applicationContext.getBean("userService");
userServiceProxy.test();
}
}
上面这种方式只能针对某一个Bean
ProxyFactoryBean还有额外的功能,比如可以把某个Advise或Advisor定义成为Bean,然后在ProxyFactoryBean中进行设置
public class UserService
{
public void test()
{
System.out.println("test");
}
}
@ComponentScan(value = "com.gax")
public class AppConfig
{
@Bean
public MethodInterceptor gaxAroundAdvise()
{
return new MethodInterceptor()
{
@Override
public Object invoke(MethodInvocation invocation)
throws Throwable
{
System.out.println("before...");
Object result = invocation.proceed();
System.out.println("after...");
return result;
}
};
}
@Bean
public ProxyFactoryBean userService()
{
UserService userService = new UserService();
ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();
proxyFactoryBean.setTarget(userService);
proxyFactoryBean.setInterceptorNames("gaxAroundAdvise");
return proxyFactoryBean;
}
}
public class Test
{
public static void main(String[] args)
{
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userServiceProxy = (UserService)applicationContext.getBean("userService");
userServiceProxy.test();
}
}
ProxyFactoryBean需要自己指定被代理的对象;BeanNameAutoProxyCreator可以通过指定某个bean的名字,来对该bean进行代理
通过BeanNameAutoProxyCreator可以对批量的Bean进行AOP,并且指定了代理逻辑,指定了一个InterceptorName,也就是一个Advise,前提条件是这个Advise也得是一个Bean,这样Spring才能找到的,但是BeanNameAutoProxyCreator的缺点很明显,它只能根据beanName来指定想要代理的Bean。
@Component
public class UserService
{
public void test()
{
System.out.println("test");
}
}
@ComponentScan(value = "com.gax")
public class AppConfig
{
@Bean
public MethodInterceptor gaxAroundAdvise()
{
return new MethodInterceptor()
{
@Override
public Object invoke(MethodInvocation invocation)
throws Throwable
{
System.out.println("before...");
Object result = invocation.proceed();
System.out.println("after...");
return result;
}
};
}
@Bean
public BeanNameAutoProxyCreator beanNameAutoProxyCreator()
{
BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator();
beanNameAutoProxyCreator.setBeanNames("userSe*");
beanNameAutoProxyCreator.setInterceptorNames("gaxAroundAdvise");
beanNameAutoProxyCreator.setProxyTargetClass(true);
return beanNameAutoProxyCreator;
}
}
public class Test
{
public static void main(String[] args)
{
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userServiceProxy = (UserService)applicationContext.getBean("userService");
userServiceProxy.test();
}
}
@Component
public class UserService
{
public void test()
{
System.out.println("test");
}
}
@ComponentScan(value = "com.gax")
public class AppConfig
{
@Bean
public MethodInterceptor gaxAroundAdvise()
{
return new MethodInterceptor()
{
@Override
public Object invoke(MethodInvocation invocation)
throws Throwable
{
System.out.println("before...");
Object result = invocation.proceed();
System.out.println("after...");
return result;
}
};
}
@Bean
public DefaultPointcutAdvisor defaultPointcutAdvisor()
{
NameMatchMethodPointcut pointcut = new NameMatchMethodPointcut();
pointcut.addMethodName("test");
DefaultPointcutAdvisor defaultPointcutAdvisor = new DefaultPointcutAdvisor();
defaultPointcutAdvisor.setPointcut(pointcut);
defaultPointcutAdvisor.setAdvice(gaxAroundAdvise());
return defaultPointcutAdvisor;
}
@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator()
{
DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
return defaultAdvisorAutoProxyCreator;
}
}
public class Test
{
public static void main(String[] args)
{
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userServiceProxy = (UserService)applicationContext.getBean("userService");
userServiceProxy.test();
}
}
通过DefaultAdvisorAutoProxyCreator会直接去找所有Advisor类型的Bean,根据Advisor中的PointCut和Advice信息,确定要代理的Bean以及代理逻辑。
简化成注解方式:
@Aspect
@Component
public class GaxAspect
{
@Before("execution(public void com.gax.service.UserService.test())")
public void gaxBefore(JoinPoint joinPoint)
{
System.out.println("gaxBefore");
}
}
要代理的类:表达式
代理逻辑:被@Before修饰的方法
Spring只要去解析这些注解就好了,解析之后得到对应的Pointcut对象、Advice对象,生成Advisor对象,扔进ProxyFactory中,进而产生对应的代理对象,具体怎么解析这些注解就是@EnableAspectJAutoProxy注解所要做的事情