目前AOP的动态代理有两部分的实现
第一部分是SDK,使用动态代理可以为一个或多个接口在运行期动态生成实现对象,生成的对象中实现接口的方法时可以添加增强代码,从而实现AOP。缺点是只能针对接口进行代理,另外由于动态代理是通过反射实现的,有时可能要考虑反射调用的开销。
第二部分是CGLIB, 动态字节码生成技术是指在运行时动态生成指定类的一个子类对象,并覆盖其中特定方法,覆盖方法时可以添加增强代码,从而实现AOP。其常用工具是cglib。
以下是关于第一部分SDK使用的笔记
AOP中的切面封装了增强(Advice)和切点(Pointcut),下面先介绍增强
接口定义:
public interface Greeting {
public void shout(String name);
}
接口的实现类定义:
public class GreetingImpl implements Greeting {
@Override
public void shout(String name) {
System.out.println("hello:"+name);
}
}
前置advice和后置advice
public class GreetingBeforeAndAfter implement MethodBeforeAdvice,AfterReturnAdvice{
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println("before");
}
public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
System.out.println("after");
}
}
测试类:
@Test
public void test(){
ProxyFactory proxy = new ProxyFactory();
proxy.setTarge(new GreetingImpl());
proxy.addAdvice(new GreetingBeforeAndAfter());
Greeting greet = (Greeting) proxy.getProxy();
greeting.shout("小法");
}
除了前置和后置的advice,还有个环绕增强类,需要实现接口org.aopalliance.intercept.MethodInterceptor。
public class GreetingBeforeAndAfterAdvice implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
before();
Object result = methodInvocation.proceed();
after();
return result;
}
public void before(){
System.out.println("before");
}
public void after(){
System.out.println("after");
}
}
将测试类中proxy工厂的一些参数写到xml文件中
<bean id="GreetingImpl" class="org.seckill.dao.aop.GreetingImpl" />
<bean id="GreetingBeforeAndAfterAdvice" class="org.seckill.dao.aop.GreetingBeforeAndAfterAdvice"/>
<bean id="GreetingProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="interfaces" value="org.seckill.dao.aop.Greeting" />
<property name="target" ref="GreetingImpl" />
<property name="interceptorNames" value="GreetingBeforeAndAfterAdvice" />
</bean>
这样就可以直接在测试类可以通过获取applicationContext的对象调用getBean()方法来获取proxy工厂
以上的做法是对方法的增强,称为织入,对于类的增强称为引入增强
在不改上述例子的情况下,创建一个新的接口名为Love
public interface Love {
void display(String name);
}
接着再创建一个advice(通知)继承一个引入(Introduction)的拦截器(Interceptor),并且实现这个接口。
public class LoveAdvice extends DelegatingIntroductionInterceptor implements Love {
/* @Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
return super.invoke(methodInvocation);
}*/
@Override
public void display(String name) {
System.out.println(name);
}
}
然后修改xml文档,将代理服务器proxy注册到spring容器中
<bean id="LoveAdvice" class="org.seckill.dao.aop.LoveAdvice" />
<bean id="LoveProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="interfaces" value="org.seckill.dao.aop.Love" />
<property name="target" ref="GreetingImpl" />
<property name="interceptorNames" value="LoveAdvice" />
<property name="proxyTargetClass" value="true" />
</bean>
其中的属性proxyTargetClass默认是false,将它置为true,将使用CGLIB的动态代理,
最后写个测试类进行测试结果
@Test
public void testAOP(){
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring/spring-config.xml");
GreetingImpl greeting = context.getBean("LoveProxy",GreetingImpl.class);
greeting.shout("小法");
Love love = (Love) greeting;
love.display("asd");
}
Love love = (Love) greeting是将目标类强制向上转型为Love接口,这就是引入增强(DelegatingIntroductionInterceptor)的特性。
网友评论