AOP创建代理的方式主要分为2大类
手动方式
也称为手动的方式,需要通过硬编码一个个创建代理。
自动化的方式
也称为批量的方式,批量的方式用在spring环境中,通过bean后置处理器来对符合条件的bean创建代理
手动的方式基本上是采用硬编码的方式,相对来说更灵活一些,可以脱离spring环境使用,而自动化的方式主要用在spring环境中,和spring集成起来更容易一些,更强大一些。
AOP创建代理相关的类
左边的ProxyCreatorSupport下面的都是手动的方式,有3个类。
右边的AbstractAutoProxyCreator下面挂的都是自动创建代理的方式,主要有5个实现类。
手动3种方式
ProxyFactory方式
这种是硬编码的方式,可以脱离spring直接使用,用到的比较多,自动化方式创建代理中都是依靠ProxyFactory来实现的
AspectJProxyFactory方式
AspectJ是一个面向切面的框架,是目前最好用,最方便的AOP框架,Spring将其集成进来了,通过Aspectj提供的一些功能实现aop代理非常方便
ProxyFactoryBean方式
Spring环境中给指定的bean创建代理的一种方式
ProxyFactoryBean
这个类实现了一个接口FactoryBean
ProxyFactoryBean就是通过FactoryBean的方式来给指定的bean创建一个代理对象。
创建代理,有3个信息比较关键:
- 需要增强的功能,这个放在通知(Advice)中实现
- 目标对象(target):表示你需要给哪个对象进行增强
- 代理对象(proxy):将增强的功能和目标对象组合在一起,然后形成的一个代理对象,通过代理对象来访问目标对象,起到对目标对象增强的效果。
使用ProxyFactoryBean也是围绕着3部分来的,ProxyFactoryBean使用的步骤:
1.创建ProxyFactoryBean对象
2.通过ProxyFactoryBean.setTargetName设置目标对象的bean名称,目标对象是spring容器中的一个bean
3.通过ProxyFactoryBean。setInterceptorNames添加需要增强的通知
4.将ProxyFactoryBean注册到Spring容器,假设名称为proxyBean
5.从Spring查找名称为proxyBean的bean,这个bean就是生成好的代理对象
栗子:
public class Service1 {
public void m1() {
System.out.println("我是 m1 方法");
}
public void m2() {
System.out.println("我是 m2 方法");
}
}
需求
在spring容器中注册上面这个类的bean,名称为service1,通过代理的方式来对这个bean进行增强,来2个通知
一个前置通知:在调用service1中的任意方法之前,输出一条信息:准备调用xxxx方法
一个环绕通知:复制统计所有方法的耗时。
下面是代码的实现:
@Configuration
public class MainConfig1 {
//注册目标对象
@Bean
public Service1 service1() {
return new Service1();
}
//注册一个前置通知
@Bean
public MethodBeforeAdvice beforeAdvice() {
MethodBeforeAdvice advice = new MethodBeforeAdvice() {
@Override
public void before(Method method, Object[] args, @Nullable Object target) throws Throwable {
System.out.println("准备调用:" + method);
}
};
return advice;
}
//注册一个后置通知
@Bean
public MethodInterceptor costTimeInterceptor() {
MethodInterceptor methodInterceptor = new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
long starTime = System.nanoTime();
Object result = invocation.proceed();
long endTime = System.nanoTime();
System.out.println(invocation.getMethod() + ",耗时(纳秒):" + (endTime - starTime));
return result;
}
};
return methodInterceptor;
}
//注册ProxyFactoryBean
@Bean
public ProxyFactoryBean service1Proxy() {
//1.创建ProxyFactoryBean
ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();
//2.设置目标对象的bean名称
proxyFactoryBean.setTargetName("service1");
//3.设置拦截器的bean名称列表,此处2个(advice1和advice2)
proxyFactoryBean.