AOP切面编程(动态代理)
Spring框架实现AOP的简单原理
动态代理
JDK实现的动态代理
1.原理
目标类与代理类实现了同一个接口。
2.实现方法
Proxy.newProxyInstance
,所需参数有三个:
- 类的加载器;动态字节码技术创建class时所需要的。
- 目标类实现的接口;
- 额外功能;
private static void test03() {
//目标类(接口)
UserService userService = new UserServiceImpl();
//创建代理类
UserService o = (UserService) Proxy.newProxyInstance(
TestUtl.getClass().getClassLoader(),/*任意一个类的加载器*/
userService.getClass().getInterfaces(),/*目标类的接口*/
new InvocationHandler() {//附加功能
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
print("--=前置通知=--");
Object invoke = null;
try {//执行目标方法
invoke = method.invoke(userService, args);
} catch (Exception e) {
print("!--异常通知!--!" + e.getCause());
throw e.getCause();
}
print("=--后置通知--=");
return invoke;
}
});
//通过代理类调用目标方法
o.login("lalala", "1234");
}
CGlib实现的动态代理
1.原理
代理类是目标类的子类。所以如果目标类用final修饰,或者目标类的方法用final修饰,则被修饰的对象、方法都不能被代理。
2.实现方法
new Enhancer()
,所需参数有三个:
- 类的加载器;动态字节码技术创建class时所需要的。
- 目标类的class对象;
- 额外功能;
private static void test04() {
//目标类(实现类)
UserServiceImpl userService = new UserServiceImpl();
//cglib创建代理类
Enhancer enhancer = new Enhancer();
enhancer.setClassLoader(ReflectUtl.class.getClassLoader());/*类的加载器*/
enhancer.setSuperclass(userService.getClass());/*目标类的class对象*/
enhancer.setCallback(new MethodInterceptor() {/*额外功能*/
@Override
public Object intercept(Object o, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
//前置通知
Object ret = null;
try {
//ret = method.invoke(userService, args);// 反射调用原始方法
ret = methodProxy.invoke(userService, objects); // 非反射调用方法
//ret = methodProxy.invokeSuper(o, objects); // 调用父类方法,入参变为子类(代理类)
} catch (Exception e) {
//异常通知
throw e.getCause();
}
//后置通知
return ret;
}
});
UserService userServiceProxy = (UserService) enhancer.create();
userServiceProxy.login("aaa", "123456");
userServiceProxy.register(new User());
}
AOP的简单原理
类BeanPostProcessor
是Spring 工厂加工原始对象的主要方法:
实现原理
public class ProxyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
InvocationHandler handler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[]
args) throws Throwable {
print("--- 前置通知 ---");
Object ret = null;
try {
ret = method.invoke(bean, args);
} catch (Exception e) {
print("--- 异常通知 ---");
throw e.getCause();
}
print("--- 后置 ---");
return ret;
}
};
/*spring默认选择jdk动态代理方式,动态代理方式的选择可通过配置实现,此处不深究。*/
return Proxy.newProxyInstance(ProxyBeanPostProcessor.class.getClassLoader(),
bean.getClass().getInterfaces(), handler);
}
}
BeanPostProcessor
的方法是对容器中所有类进行操作的,所以此处还应有切点的逻辑。用来确定哪些类需要添加哪些额外功能。
配置文件
<bean id="userService" class="com.*.*.UserServiceImpl"/>
<!--1.实现 BeanPostProcessor 进行加工-->
<!--2.配置文件中对 BeanPostProcessor 进行配置-->
<bean id="proxyBeanPostProcessor" class="com.*.*.ProxyBeanPostProcessor"/>