千家信息网

自动注解实现Spring IOC和事务管理的示例分析

发表于:2024-12-05 作者:千家信息网编辑
千家信息网最后更新 2024年12月05日,自动注解实现Spring IOC和事务管理的示例分析,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。自定义注解实现spring的IOC以及
千家信息网最后更新 2024年12月05日自动注解实现Spring IOC和事务管理的示例分析

自动注解实现Spring IOC和事务管理的示例分析,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。

自定义注解实现spring的IOC以及事务管理功能

思路分析

IOC

IOC即控制反转,我们要把对象的创建通过注解来实现

  • @Service 类中声明了@Service注解的对象,我们就对它的实例化进行管理。(这里注解的名字无所谓,我们实现相应的功能即可)

  • @Autowired 类中的属性声明了@Autowired注解的,我们就对该属性进行依赖注入 在程序运行前,我们通过扫描所有的类文件,然后找出声明了@Service注解的类,进行实例化,然后加入到我们的一个Map集合中,同时查找该类中是否有声明@Autowired注解的属性,并进行标记。 再次遍历声明了@Service注解的类,然后注入声明@Autowired注解属性的类。这样我们就把对象的创建以及依赖的注入完成了。

事务管理功能

事务管理需要我们遵循事务的ACID原则

  • @Transactional 类中或者方法中声明了@Transactional注解的我们就要对改对象或者方法添加事务控制功能 首先我们先扫描所有类文件,找出声明了@Transactional注解的类或者方法,准备好一个List集合,如果注解声明在类上,我们就把类中所有的方法放入集合中,如果注解是在方法上,我们直接把方法加入到List集合中。 然后我们通过代理(动态代理或者cglib代理)给这些方法添加事务控制功能

代码实现(只列出核心代码片段)

创建ApplicationContext接口

public interface ApplicationContext {        Object getBean(String name);     T getBean(String name, Class requiredType);}

创建AnnotationConfigApplicationContext对象,实现接口方法

这是一个核心配置类,主要实现了以下三个功能

  • 获取所有配置了@Service注解的类,并实例化,放入Map中

  • 对于类中添加@Autowired注解的属性进行依赖注入

  • 对于添加了@Transactional注解的属性或者方法进行事务增强

public class AnnotationConfigApplicationContext implements ApplicationContext {    /**     * 存放bean     */    private final Map beanMap = new HashMap<>();    /**     * 先把包名转换为路径,首先得到项目的classpath     */    private final String CLASSPATH = this.getClass().getResource("/").getPath();    public AnnotationConfigApplicationContext(String... basePackages) {        try {            scanPackages(basePackages);        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {            e.printStackTrace();        }    }    /**     * 扫描所有包 并实现bean对象的创建,依赖注入,增强事务     * @param basePackages     * @throws ClassNotFoundException     * @throws InstantiationException     * @throws IllegalAccessException     */    private void scanPackages(String[] basePackages) throws ClassNotFoundException, InstantiationException, IllegalAccessException {        // 设置获取所有配置Service注解的对象        setBeanDefinition(basePackages);        // 设置依赖关系        setBeanDepend();        // 设置事务增强        setTransaction();    }    /**     * 获取所有需要管理的对象     *     * @param basePackages 需要扫描的包     * @throws ClassNotFoundException     * @throws IllegalAccessException     * @throws InstantiationException     */    private void setBeanDefinition(String[] basePackages) throws ClassNotFoundException, IllegalAccessException, InstantiationException {        // 获取所有类路径下的class文件        List classPaths = new ArrayList<>();        for (String basePackage : basePackages) {            //然后把我们的包名basPath转换为路径名            basePackage = basePackage.replace(".", File.separator);            //然后把classpath和basePack合并            String searchPath = CLASSPATH + basePackage;            getFile(classPaths, new File(searchPath));        }        // 找出所有有@Service注解的类,加入到beanMap中        for (String s : classPaths) {            s = s.replace(CLASSPATH, "").replace("/", ".").replace(".class", "");            Class clazz = Class.forName(s);            Service service = (Service) clazz.getAnnotation(Service.class);            if (service != null) {                BeanDefinition beanDefinition = new BeanDefinition();                beanDefinition.setBeanObject(clazz.newInstance());                // 设置bean name                String value = service.value();                // 如果没有自定义bean name,设置bean name为class name                if ("".equals(value)) {                    value = clazz.getName();                    value = value.substring(value.lastIndexOf(".") + 1);                    value = value.substring(0, 1).toLowerCase() + value.substring(1);                }                beanDefinition.setBeanName(value);                // 是否有依赖关系                Field[] declaredFields = clazz.getDeclaredFields();                for (Field declaredField : declaredFields) {                    declaredField.setAccessible(true);                    Autowired autowired = declaredField.getAnnotation(Autowired.class);                    // 如果类属性有@Autowired注解,把依赖对象放入BeanDefinition的dependBeanName集合中                    if (autowired != null) {                        beanDefinition.setAutoWired(true);                        beanDefinition.getDependBeanName().add(declaredField.getName());                    }                }                // 是否有父接口,为后面增强使用动态代理还是cglib代理做准备                Class[] interfaces = clazz.getInterfaces();                if (interfaces.length > 0) {                    beanDefinition.setHaveParent(true);                }                // 是否有事务注解,如果有加入到BeanDefinition对象的transactionMethods属性中                Annotation annotation = clazz.getAnnotation(Transactional.class);                Method[] methods = clazz.getDeclaredMethods();                //如果@Transactional注解出现在类上面,把类下所有的方法都加入到待添加事务的列表中                if (annotation != null) {                    for (Method method : methods) {                        beanDefinition.getTransactionMethods().add(method);                    }                } else {                    // 如果@Transactional在某个方法上面,把该方法加入到BeanDefinition对象的transactionMethods属性中                    for (Method method : methods) {                        Transactional methodAnnotation = method.getAnnotation(Transactional.class);                        if (methodAnnotation != null) {                            beanDefinition.getTransactionMethods().add(method);                        }                    }                }                // 将添加事务之后的对象重新加入到beanMap中                beanMap.put(beanDefinition.getBeanName(), beanDefinition);            }        }    }    /**     * 遍历所有bean,找出有依赖关系的bean,注入     */    private void setBeanDepend() {        for (Map.Entry next : beanMap.entrySet()) {            BeanDefinition beanDefinition = next.getValue();            //如果有AutoWired注解,设置值            if (beanDefinition.isAutoWired()) {                Object object = beanDefinition.getBeanObject();                Class definitionClass = object.getClass();                List beanNames = beanDefinition.getDependBeanName();                beanNames.forEach(w -> {                    try {                        // 获取需要进行注入的对象                        Field declaredField = definitionClass.getDeclaredField(w);                        // 暴力访问                        declaredField.setAccessible(true);                        // 给依赖对象赋值                        declaredField.set(object, getBean(w));                    } catch (NoSuchFieldException | IllegalAccessException e) {                        e.printStackTrace();                    }                });                // 组装好的对象重新放入map中                beanMap.put(beanDefinition.getBeanName(), beanDefinition);            }        }    }    /**     * 配置事务增强     */    private void setTransaction() {        for (Map.Entry next : beanMap.entrySet()) {            BeanDefinition definition = next.getValue();            //获取需要开启事务管理的类下的所有方法            List transactionMethods = definition.getTransactionMethods();            ProxyFactory proxyFactory = new ProxyFactory();            // 根据代理对象是实现接口,来决定采用动态代理还是cglib代理            if (!definition.isHaveParent()) {                proxyFactory = new ProxyFactory(new CglibProxy());            }            //给方法配置事务增强            Object withTransaction = proxyFactory.getProxyWithTransaction(definition.getBeanObject(), transactionMethods);            definition.setBeanObject(withTransaction);            //把增强之后的对象重新放入到beanMap中            beanMap.put(next.getKey(), definition);        }    }    private void getFile(List classPaths, File file) {        //文件夹递归        if (file.isDirectory()) {            File[] files = file.listFiles();            if (files != null) {                for (File f1 : files) {                    getFile(classPaths, f1);                }            }        } else {            //标准文件获取class文件            if (file.getName().endsWith(Constant.FILE_TYPE_CLASS)) {                //如果是class文件我们就放入我们的集合中。                classPaths.add(file.getPath());            }        }    }    @Override    public Object getBean(String name) {        return beanMap.get(name).getBeanObject();    }    @Override    public  T getBean(String name, Class requiredType) {        Object o = beanMap.get(name).getBeanObject();        if (o.getClass() == requiredType) {            return (T) o;        }        return null;    }}

事务增强的实现

对于事务的增强,我们需要依赖代理来实现。代理我们使用了动态代理和cglib代理两种,对于需要代理对象实现接口的,我们使用动态代理;对于没有实现接口的对象,我们使用cglib代理。下面看下具体实现。

创建AopProxy接口
public interface AopProxy {    /**     * 创建带事务的代理     *     * @param o       代理对象     * @param methods 代理对象中需要添加事务的方法     * @return 增强之后的代理对象     */    abstract Object createProxyWithTransaction(Object o, List methods);}
动态代理DynamicProxy的实现
public class DynamicProxy implements AopProxy {    @Override    public Object createProxyWithTransaction(Object o, List methods) {        return Proxy.newProxyInstance(o.getClass().getClassLoader(), o.getClass().getInterfaces(), (proxy, method, args) -> {            Object invoke = null;            boolean anyMatch = methods.stream().anyMatch(w -> w.getName().equals(method.getName()));            if (anyMatch) {                TransactionManager.getInstance().beginTransaction();                try {                    invoke = method.invoke(o, args);                    TransactionManager.getInstance().commit();                } catch (Exception e) {                    TransactionManager.getInstance().rollback();                    throw e;                }                return invoke;            }            invoke = method.invoke(o, args);            return invoke;        });    }}
cglib代理的实现
public class CglibProxy implements AopProxy {    @Override    public Object createProxyWithTransaction(Object o, List methods) {        Enhancer enhancer = new Enhancer();        enhancer.setSuperclass(o.getClass());        enhancer.setCallback((MethodInterceptor) (o1, method, objects, methodProxy) -> {            Object invoke;            boolean anyMatch = methods.stream().anyMatch(w -> w.getName().equals(method.getName()));            if (anyMatch) {                TransactionManager.getInstance().beginTransaction();                try {                    invoke = method.invoke(o, objects);                    TransactionManager.getInstance().commit();                } catch (Exception e) {                    TransactionManager.getInstance().rollback();                    throw e;                }                return invoke;            }            invoke = method.invoke(o, objects);            return invoke;        });        return enhancer.create();    }}

看完上述内容,你们掌握自动注解实现Spring IOC和事务管理的示例分析的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注行业资讯频道,感谢各位的阅读!

0