spring aop动态代理开发
一、什么是动态代理
动态代理就是,在程序运行期,创建目标对象的代理对象,并对目标对象中的方法进行功能性增强的一种技术。在生成代理对象的过程中,目标对象不变,代理对象中的方法是目标对象方法的增强方法。可以理解为运行期间,对象中方法的动态拦截,在拦截方法的前后执行功能操作。
代理类在程序运行期间,创建的代理对象称之为动态代理对象。这种情况下,创建的代理对象,并不是事先在Java代码中定义好的。而是在运行期间,根据我们在动态代理对象中的“指示”,动态生成的。也就是说,你想获取哪个对象的代理,动态代理就会为你动态的生成这个对象的代理对象。动态代理可以对被代理对象的方法进行功能增强。有了动态代理的技术,那么就可以在不修改方法源码的情况下,增强被代理对象的方法的功能,在方法执行前后做任何你想做的事情。
Spring Aop 面向切面编程
面向切面编程采用动态代理的方式进行对相关方法增强
以下采用JDK官方提供的Proxy类创建代理对象
代码如下
public class MockAopBeanPostProcessor implements BeanPostProcessor , ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
//目的:对UserServiceImpl中的show1和show2方法进行增强,增强方法存在与MyAdvice中
//问题1:筛选service.impl包下的所有的类的所有方法都可以进行增强,解决方案if-else
//问题2:MyAdvice怎么获取到?解决方案:从Spring容器中获得MyAdvice
if(bean.getClass().getPackage().getName().equals("com.itheima.service.impl")){
//生成当前Bean的Proxy对象
Object beanProxy = Proxy.newProxyInstance(
bean.getClass().getClassLoader(),
bean.getClass().getInterfaces(),
(Object proxy, Method method, Object[] args) -> {
MyAdvice myAdvice = applicationContext.getBean(MyAdvice.class);
//执行增强对象的before方法
myAdvice.beforeAdvice();
//执行目标对象的目标方法
Object result = method.invoke(bean, args);
//执行增强对象的after方法
myAdvice.afterAdvice();
return result;
}
);
return beanProxy;
}
return bean;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
其实我们对UserService进行了增强
UserServiceImpl继承了UserService接口 ,
增强对象的增强方法我们设置在MyAdvice类里
最后 , 配置文件不可少
用xml配置方式配置spring容器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
">
<!--配置目标类-->
<bean id="userService" class="com.itheima.service.impl.UserServiceImpl"></bean>
<!--配置的通知类-->
<bean id="myAdvice" class="com.itheima.advice.MyAdvice"></bean>
<bean class="com.itheima.processor.MockAopBeanPostProcessor"></bean>
</beans>
在测试类里测试即可
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService bean = app.getBean(UserService.class);
bean.show1();
方法show1()得到了增强 (其实UserServiceImpl里的每一个方法都得到了增强, 在此演示show1())