一:AOP 简介
1:AOP的概念
AOP,Aspect Oriented Programming,面向切面编程,是对面向对象编程OOP的升华。OOP是纵向对一个事物的抽象,一个对象包括静态的属性信息,包括动态的方法信息等。而AOP是横向的对不同事物的抽象,属性与属性、方法与方法、对象与对象都可以组成一个切面,而用这种思维去设计编程的方式叫做面向切面编程。
2:AOP思想的实现方案
动态代理技术,在运行期间,对目标对象的方法进行增强,代理对象同名方法内可以执行原有逻辑的同时嵌入执行其他增强逻辑或其他对象的方法。
3:模拟AOP的基础代码-代码git地址
学习BeanPostProcessor时,在BeanPostProcessor的after方法中使用动态代理对Bean进行了增强,实际存储到单例池singleObjects中的不是当前目标对象本身,而是当前目标对象的代理对象Proxy,这样在调用目标对象方法时,实际调用的是代理对象Proxy的同名方法,起到了目标方法前后都进行增强的功能,对该方式进行一下优化,将增强的方法提取出去到一个增强类中,且只对com.zgs.service.impl包下的任何类的任何方法进行增强。
-
SpringConfig
@Configuration
@ComponentScan(basePackages = "com.zgs")
public class SpringConfig {
}
-
ApplicationContextTest
public class ApplicationContextTest {public static void main(String[] args) {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
// ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);UserService userService = applicationContext.getBean(UserService.class);userService.show1();}
}
-
MyAdvice
@Component
public class MyAdvice {public void before() {System.out.println("MyAdvice的before方法执行.....");}public void after() {System.out.println("MyAdvice的after方法执行.....");}
}
-
MockAopBeanPostProcessor
@Component
public class MockAopBeanPostProcessor implements BeanPostProcessor, ApplicationContextAware {private ApplicationContext applicationContext;@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (bean.getClass().getPackage().getName().equals("com.zgs.service.impl")) {//对bean进行动态代理增强-生成bean的代理类Object proxyBean = Proxy.newProxyInstance(bean.getClass().getClassLoader(),bean.getClass().getInterfaces(),(Object proxy, Method method, Object[] args) -> {//拦截目标方法,调用目标方法,并做增强//前置增强MyAdvice myAdvice = applicationContext.getBean(MyAdvice.class);myAdvice.before();//调用目标方法Object obj = method.invoke(bean, args);//调用后置增强myAdvice.after();return obj;});return proxyBean;}return bean;}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;}
}
-
UserService
public interface UserService {void show1();void show2();
}
-
UserServiceImpl
@Component
public class UserServiceImpl implements UserService {@Overridepublic void show1() {System.out.println("UserServiceImpl的show1方法执行");}@Overridepublic void show2() {System.out.println("UserServiceImpl的show2方法执行");}
}
- applicationContext.xml
<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsd"><bean id="userService" class="com.zgs.service.impl.UserServiceImpl"></bean><bean id="userDao" class="com.zgs.dao.impl.UserDaoImpl"></bean><bean id="myAdvice" class="com.zgs.advice.MyAdvice"></bean><bean id="mockAopBeanPostProcessor" class="com.zgs.post.MockAopBeanPostProcessor"></bean>
</beans>
- 输出结果
4:AOP相关概念
二:基于xml配置的AOP
1:xml方式AOP快速入门
1.1:AOP基础代码问题
- 被增强的包名在代码写死了
- 通知对象的方法在代码中写死了
1.2:通过配置文件的方式去解决上述问题
- 配置哪些包、哪些类、哪些方法需要被增强
- 配置目标方法要被哪些通知方法所增强,在目标方法执行之前还是之后执行增强
1.3:xml方式配置AOP的步骤:
- 导入AOP相关坐标;
<dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.6</version>
</dependency>
- 准备目标类、准备增强类,并配置给Spring管理;
- 配置切点表达式(哪些方法被增强);
- 配置织入(切点被哪些通知方法增强,是前置增强还是后置增强)。
1.4:代码
- applicationContext.xml
<?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"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><!--目标类--><bean id="userService" class="com.zgs.service.impl.UserServiceImpl"></bean><!--通知类--><bean id="myAdvice" class="com.zgs.advice.MyAdvice"></bean><!--aop配置--><aop:config><!--配置切点表达式 目的知道那些方法需要被增强--><aop:pointcut id="myPointCut" expression="execution(void com.zgs.service.impl.UserServiceImpl.show1())"/>
<!-- <aop:pointcut id="myPointCut2" expression="execution(void com.zgs.service.impl.UserServiceImpl.show2())"/>--><!--配置织入 目的知道那些方法需要被增强--><aop:aspect ref="myAdvice"><aop:before method="beforeAdvice" pointcut-ref="myPointCut"/><aop:after method="afterAdvice" pointcut-ref="myPointCut"/></aop:aspect></aop:config><!-- <bean id="userDao" class="com.zgs.dao.impl.UserDaoImpl"></bean>-->
<!-- <bean id="mockAopBeanPostProcessor" class="com.zgs.post.MockAopBeanPostProcessor"></bean>-->
</beans>
-
ApplicationContextTest
public class ApplicationContextTest {public static void main(String[] args) {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
// ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);UserService userService = applicationContext.getBean(UserService.class);userService.show1();}
}
-
MyAdvice
@Component
public class MyAdvice {public void beforeAdvice() {System.out.println("MyAdvice的before增强方法执行.....");}public void afterAdvice() {System.out.println("MyAdvice的after增强方法执行.....");}
}
- 结果