浅谈基于动态代理的Spring AOP原理
【摘要】 浅谈基于动态代理的Spring AOP原理 1 什么时候会用到AOP?Bean的创建和初始化过程中增加环绕、前置、后置方法事务、日志拦截器…这篇文章就着重讲解下Bean创建和初始化的过程中使用到的AOP原理 2 回顾Bean的创建过程在Bean的创建过程中比较重要的一步就是对Bean进行AOP处理,但是不是必要的,接下来我们从头开始手写一个自己的Spring进行实现。 3 扫描Bean这里...
浅谈基于动态代理的Spring AOP原理
1 什么时候会用到AOP?
- Bean的创建和初始化过程中
- 增加环绕、前置、后置方法
- 事务、日志
- 拦截器
- …
这篇文章就着重讲解下Bean创建和初始化的过程中使用到的AOP原理
2 回顾Bean的创建过程
在Bean的创建过程中比较重要的一步就是对Bean进行AOP处理,但是不是必要的,接下来我们从头开始手写一个自己的Spring进行实现。
3 扫描Bean
这里的流程主要是new一个ApplicationContext,传入xml文件或配置类,以此来扫描固定包下的类。
/**
* 构造方法
*
* @param configClass
*/
public MyApplicationContext(Class configClass) {
this.configClass = configClass;
//扫描Bean
scanBean();
//根据BeanDefinition创建Bean
for (Map.Entry<String, MyBeanDefinition> beanDefinitionEntry : beanDefinitionMap.entrySet()) {
String key = beanDefinitionEntry.getKey();
MyBeanDefinition value = beanDefinitionEntry.getValue();
if (ScopeUtils.SINGLETON.equals(value.getScope())) {
Object bean = createBean(key,value);
singletonPool.put(key, bean);
}
}
}
/**
* 扫描Bean
*/
private void scanBean() {
//拿到配置类之后对其进行解析 扫描
MyComponentScan scan = (MyComponentScan) configClass.getDeclaredAnnotation(MyComponentScan.class);
String path = scan.value();
//根据路径进行扫描
ClassLoader classLoader = MyComponentScan.class.getClassLoader();
String newPath = path.replace('.', '/');
//获取文件路径
URL url = classLoader.getResource(newPath);
File file = new File(url.getFile());
if (file.isDirectory()) {
File[] files = file.listFiles();
//获取到该包下的每个文件(Class)
for (File f : files) {
String absolutePath = f.getAbsolutePath();
//判断是不是.class文件
if (absolutePath.endsWith(".class")) {
String className = absolutePath.substring(absolutePath.indexOf("org"), absolutePath.indexOf(".class"));
String name = className.replace("\\", ".");
try {
Class<?> clazz = classLoader.loadClass(name);
//判断是否有MyComponent注解
if (clazz.isAnnotationPresent(MyComponent.class)) {
MyComponent component = clazz.getDeclaredAnnotation(MyComponent.class);
String beanName = component.value();
if (beanName.getBytes().length == 0) {
beanName = name.substring(name.lastIndexOf(".") + 1);
beanName = beanName.substring(0, 1).toLowerCase(Locale.ROOT) + beanName.substring(1);
}
MyBeanDefinition beanDefinition = new MyBeanDefinition();
beanDefinition.setClazz(clazz);
//判断bean的作用域
if (clazz.isAnnotationPresent(MyScope.class)) {
MyScope scope = clazz.getDeclaredAnnotation(MyScope.class);
beanDefinition.setScope(scope.value());
} else {
beanDefinition.setScope("singleton");
}
//判断是否实现了BeanPostProcessor
if (MyBeanPostProcessor.class.isAssignableFrom(clazz)) {
//这一步简化,非spring源码
MyBeanPostProcessor instance = (MyBeanPostProcessor) clazz.getDeclaredConstructor().newInstance();
beanPostProcessorList.add(instance);
}
//将该bean的Definition放入map中
beanDefinitionMap.put(beanName, beanDefinition);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
4 创建Bean
/**
* 创建bean
*
* @param beanDefinition
* @return
*/
public Object createBean(String beanName,MyBeanDefinition beanDefinition) {
Class clazz = beanDefinition.getClazz();
Object newInstance = null;
try {
newInstance = clazz.getConstructor().newInstance();
//处理依赖注入
for (Field field : clazz.getDeclaredFields()) {
if (field.isAnnotationPresent(MyAutowired.class)) {
Object bean = getBean(field.getName());
field.setAccessible(true);
field.set(newInstance, bean);
}
}
//BeanPostProcessor初始化前
for (MyBeanPostProcessor processor : beanPostProcessorList) {
//放入的和传出的不一定是同一个对象
newInstance = processor.postProcessBeforeInitialization(newInstance, beanName);
}
//Bean的初始化方法
if (newInstance instanceof MyInitializingBean) {
((MyInitializingBean) newInstance).afterPropertiesSet();
}
//BeanPostProcessor初始化后
for (MyBeanPostProcessor processor : beanPostProcessorList) {
//放入的和传出的不一定是同一个对象
newInstance = processor.postProcessAfterInitialization(newInstance, beanName);
}
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return newInstance;
}
5 获取Bean
/**
* getBean方法
*
* @param beanName
* @return
*/
public Object getBean(String beanName) {
if (beanDefinitionMap.containsKey(beanName)) {
MyBeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if (ScopeUtils.SINGLETON.equals(beanDefinition.getScope())) {
return singletonPool.get(beanName);
} else {
return createBean(beanName,beanDefinition);
}
} else {
throw new MyNoSuchBeanDefinitionException("没有这个Bean");
}
}
6 实现自己的BeanPostProcessor
Spring初始化Bean时对Bean的增强就是在BeanPostProcess方法中进行实现的,postProcessBeforeInitialization做前置处理,postProcessAfterInitialization做后置处理。可以看下Spring源码
/**
* @desc: BeanPostProcessor抽象
* @author: YanMingXin
* @create: 2021/9/16-15:01
**/
public interface MyBeanPostProcessor {
Object postProcessBeforeInitialization(Object bean,String beanName);
Object postProcessAfterInitialization(Object bean,String beanName);
}
实现该方法,使用JDK动态代理将Bean包装
/**
* @desc: MyBeanPostProcessorHandler
* @author: YanMingXin
* @create: 2021/9/17-10:25
**/
@MyComponent
public class MyBeanPostProcessorHandler implements MyBeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
if ("studentServiceImpl".equals(beanName)) {
System.out.println("初始化前");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
if ("studentServiceImpl".equals(beanName)) {
Object proxyInstance = Proxy.newProxyInstance(MyBeanPostProcessorHandler.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//代理逻辑
System.out.println("代理逻辑");
//对象的方法
return method.invoke(bean, args);
}
});
System.out.println("初始化后");
return proxyInstance;
}
return bean;
}
}
7 测试
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)