1 前言
AOP,Aspect Oriented Programming,面向切面编程,是对面向对象编程OOP的升华。OOP是纵向对一个事物的抽象,一个对象包括静态的属性信息,包括动态的方法信息等。而AOP是横向的对不同事物的抽象,属性与属性、方法与方法、对象与对象都可以组成一个切面,而用这种思维去设计编程的方式叫做面向切面编程。
将两个对象的若干方法临时组装在一起,使用更加灵活。resist 是主方法,getException为增强方法。
1.1 AOP思想的实现方案
动态代理技术,在运行期间,对目标对象的方法进行增强,代理对象同名方法内可以执行原有逻辑的同时嵌入执行其他增强逻辑或其他对象的方法。
2 简单模拟AOP实现
【第一步】目标bean(等待被增强)
package org.example.service.impl;
import org.example.service.UserService;
/**
* @author : msf
* @date : 2023/1/26
*/
public class UserServiceImpl implements UserService {
@Override
public void show1() {
System.out.println("show1....");
}
@Override
public void show2() {
System.out.println("show2....");
}
}
【第二步】增强的类
// 增强类,内部提供增强方法
public class MyAdvice {
public void beforeAdvice(){
System.out.println("前置增强...");
}
public void afterAdvice(){
System.out.println("后置增强...");
}
}
【第三步】配置处理器
实现beanpostpropocessor和applicationaware
难点
1. 筛选service.impl包下的所有类都会增强? -->通过反射获取
2. MyAdvice 怎么获取? -->从spring容器中获取。
package org.example.processor;
import org.example.advice.MyAdvice;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @author : msf
* @date : 2023/1/26
*/
public class AopBeanPostProcessor implements BeanPostProcessor, ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException {
// 对userServiceImpl 的两个方法进行增强
// 问题1. 筛选service.impl包下的所有类都会增强? -->通过反射获取
// 问题2. MyAdvice 怎么获取? -->从spring容器中获取。
if ("org.example.service.impl".equals(bean.getClass().getPackage().getName())) {
// 生成当前bean的proxy对象
Object beanProxy = Proxy.newProxyInstance(
bean.getClass().getClassLoader(),
bean.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 获取增强对象的增强方法
MyAdvice myAdvice = applicationContext.getBean("myAdvice", MyAdvice.class);
myAdvice.beforeAdvice();
Object result = method.invoke(bean, args);
myAdvice.afterAdvice();
return result;
}
}
);
return beanProxy;
}
return bean;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
【第四步】通过xml进行IoC
<?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="org.example.service.impl.UserServiceImpl"/>
<!--配置增强对象-->
<bean id="myAdvice" class="org.example.advice.MyAdvice"/>
<!--增强逻辑-->
<bean class="org.example.processor.AopBeanPostProcessor"/>
<!----><context:property-placeholder location="classpath:jdbc.properties"/>
<!--注解组件扫描:扫描指定的基本包及其子包下的类,识别使用@Component注解-->
<!-- <context:component-scan base-package="org.example"/>-->
</beans>
【第五步】测试
public class ApplicationContextTest {
public static void main(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = context.getBean("userService", UserService.class);
userService.show1();
//System.out.println("userService = " + userService);
}
}
结果
总结如下