目录
- package com.example.Processor;
-
- import com.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 org.springframework.stereotype.Component;
-
- import java.lang.reflect.Method;
- import java.lang.reflect.Proxy;
-
- @Component
- public class MockAopBeanPostProcessor implements BeanPostProcessor, ApplicationContextAware {
- private ApplicationContext applicationContext;
-
- @Override
- public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
- // 目的:对UserServiceImpl中的show1和show2方法进行增强,增强的方法存在于MyAdvice中
- // 问题:设定增强范围(判断语句)、如何获取MyAdvice(从Spring容器中获取)
- if (bean.getClass().getPackage().getName().equals("com.example.Service.ServiceImpl")) {
- // 生成当前Bean的Proxy对象
- Object beanProxy = Proxy.newProxyInstance(
- bean.getClass().getClassLoader(),
- bean.getClass().getInterfaces(),
- (Object proxy, Method method, Object[] args) -> {
- // 执行增强对象的before方法
- MyAdvice myAdvice = applicationContext.getBean(MyAdvice.class);
- 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;
- }
- }
上述代码是实现bean对象增强的核心过程,指定了需要增强bean对象的范围,以及具体的增强逻辑。实现的两个接口作用具体参照文章:SpringBean的生命周期-CSDN博客
- package com.example.Service.ServiceImpl;
-
- import com.example.Service.UserService;
- import org.springframework.stereotype.Service;
-
- @Service
- public class UserServiceImpl implements UserService {
- @Override
- public void show1() {
- System.out.println("show1.....");
- }
-
- @Override
- public void show2() {
- System.out.println("show2.....");
- }
- }
通知类
- package com.example.advice;
-
-
- import org.springframework.stereotype.Component;
-
- // 自定义增强类,内部提供增强方法
- @Component("myAdvice")
- public class MyAdvice {
- public void beforeAdvice() {
- System.out.println("前置增强");
-
- }
-
- public void afterAdvice() {
- System.out.println("后置增强");
-
- }
- }
测试类
- package com.example.Test;
-
-
- import com.example.Service.UserService;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
-
- public class TestMyAOP {
- public static void main(String[] args) {
- ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
- UserService userService = applicationContext.getBean(UserService.class);
- userService.show1();
- }
- }
ps:在上述举例代码中,我是在Spring框架下使用注解的的方式进行bean对象的注册,同时需要在配置文件中设置组件扫描的范围,以此让注解进行生效 当然你也可以使用xml配置文件的方式,将对应类的bean对象交给Spring容器管理,具体如何实现可以参考我的往期Spring注解开发、基于Xml方式配置Bean的相关文章
概念 | 描述 |
---|---|
切面(Aspect) | 增强和切入点的代码组合 |
连接点(Joinpoint) | 目标对象可以被增强的方法 |
通知/增强(Advice) | 增强部分的代码逻辑 |
切点(切入点)(Pointcut) | 目标对象中实际被增强的方法,连接点包括切点。 |
引入(Introduction) | 在不修改类代码的前提下,引入新的接口和功能。 |
织入(Weaving) | 把切面(增强和切入点代码的组合)应用到目标对象并创建新的代理对象的过程。 |
目标对象(Target Object) | 被增强的方法所在的对象 |
代理对象(Proxy) | 对目标对象增强后的对象,客户端实际调用的对象 |