aop配置多个包_自定义IOC容器和AOP框架

回到目录:

OrangeZh:拉勾教育:JAVA高薪训练营 学习笔记​zhuanlan.zhihu.com
a36fdbe43eed9315d0ae3589dff6be49.png

介绍

自定义IOC容器和AOP框架

实现简单的Spring的Ioc容器,包含容器初始化,Bean实例化,实现@Service、@Autowired、@Transactional、@Bean、@Value等注解

什么是IOC

IoC Inversion of Control (控制反转/反转控制),它是⼀个技术思想,不是⼀个技术实现

描述的事情:Java开发领域对象的创建,管理的问题

传统开发⽅式:⽐如类A依赖于类B,往往会在类A中new⼀个B的对象

IoC思想下开发⽅式:我们不⽤⾃⼰去new对象了,⽽是由IoC容器(Spring框架)去帮助我们实例化对象并且管理它,我们需要使⽤哪个对象,去问IoC容器要即可

我们丧失了⼀个权利(创建、管理对象的权利),得到了⼀个福利(不⽤考虑对象的创建、管理等⼀系列事情)

为什么叫做控制反转?

控制:指的是对象创建(实例化、管理)的权利

反转:控制权交给外部环境了(spring框架、IoC容器)

IoC解决对象之间的耦合问题

IOC和DI描述的是同⼀件事情,只不过⻆度不⼀样

8c26c7ad005be3950da479219f5afad2.png
IOC容器示例

什么是AOP

AOP: Aspect oriented Programming ⾯向切⾯编程/⾯向⽅⾯编程

AOP是OOP的延续,从OOP说起

OOP三⼤特征:封装、继承和多态

OOP是⼀种垂直继承体系,而AOP是一种纵向的体系

比如:想在多个业务方法运行前后记录日志,为了不影响业务代码那么就抽象出一个横切逻辑单读维护

手写实现IOC和AOP

案例实现了IOC容器的管理,包含容器初始化,Bean实例化,实现@Service、@Autowired、@Transactional、@Bean、@Value等注解,其中@Transactional就属于AOP的一种实现(动态代理)

  • 导入必要的依赖包
<dependencies>
        <!-- 单元测试Junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>

        <!-- mysql数据库驱动包 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.21</version>
        </dependency>
        <!--druid连接池-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.21</version>
        </dependency>

        <!-- servlet -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>

        <!-- jackson依赖 -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.6</version>
        </dependency>

        <!--dom4j依赖-->
        <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6.1</version>
        </dependency>
        <!--xpath表达式依赖-->
        <dependency>
            <groupId>jaxen</groupId>
            <artifactId>jaxen</artifactId>
            <version>1.1.6</version>
        </dependency>
        <!--引入cglib依赖包-->
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>2.1_2</version>
        </dependency>
    </dependencies>
  • 创建数据库外部配置文件 jdbc.properties
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ozdemo?characterEncoding=utf-8
jdbc.username=root
jdbc.password=123456
  • 创建数据库表
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for account
-- ----------------------------
DROP TABLE IF EXISTS `account`;
CREATE TABLE `account`  (
  `aid` int(11) NOT NULL AUTO_INCREMENT,
  `cardNo` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
  `money` int(11) NOT NULL DEFAULT 0,
  PRIMARY KEY (`aid`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of account
-- ----------------------------
INSERT INTO `account` VALUES (1, '6029621011001', '韩梅梅', 10000);
INSERT INTO `account` VALUES (2, '6029621011000', '李大雷', 10000);

SET FOREIGN_KEY_CHECKS = 1;
  • 创建必要的注解类 @Service、@Autowired、@Transactional、@Bean、@Value、@Component等

@Transactional示例:其它类似

/**
 * @Description: @Transactional注解
 * @Author: Created by OrangeZh
 * @Date: Created in 2020/9/4 17:37
 */
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
    String value() default "";

    String transactionManager() default "";
}
  • (AOP关建代码)创建动态代理工厂类 ProxyFactory和事务类 TransactionManager
/**
 * 代理对象工厂:生成代理对象的
 */
@Component("proxyFactory")
public class ProxyFactory {
    @Autowired
    private TransactionManager transactionManager;

    /**
     * Jdk动态代理
     *
     * @param obj 委托对象
     * @return 代理对象
     */
    public Object getJdkProxy(Object obj) {
        // 获取代理对象
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Object result = null;
                try {
                    // 开启事务(关闭事务的自动提交)
                    transactionManager.beginTransaction();
                    result = method.invoke(obj, args);
                    // 提交事务
                    transactionManager.commit();
                } catch (Exception e) {
                    e.printStackTrace();
                    // 回滚事务
                    transactionManager.rollback();
                    // 抛出异常便于上层servlet捕获
                    throw e;
                }
                return result;
            }
        });
    }


    /**
     * 使用cglib动态代理生成代理对象
     *
     * @param obj 委托对象
     * @return
     */
    public Object getCglibProxy(Object obj) {
        return Enhancer.create(obj.getClass(), new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                Object result = null;
                try {
                    // 开启事务(关闭事务的自动提交)
                    transactionManager.beginTransaction();
                    result = method.invoke(obj, objects);
                    // 提交事务
                    transactionManager.commit();
                } catch (Exception e) {
                    e.printStackTrace();
                    // 回滚事务
                    transactionManager.rollback();
                    // 抛出异常便于上层servlet捕获
                    throw e;
                }
                return result;
            }
        });
    }
}

/**
 * 事务管理器类:负责手动事务的开启、提交、回滚
 */
@Component("transactionManager")
public class TransactionManager {

    @Autowired
    private ConnectionUtils connectionUtils;

    // 开启手动事务控制
    public void beginTransaction() throws SQLException {
        connectionUtils.getCurrentThreadConn().setAutoCommit(false);
    }

    // 提交事务
    public void commit() throws SQLException {
        connectionUtils.getCurrentThreadConn().commit();
    }

    // 回滚事务
    public void rollback() throws SQLException {
        connectionUtils.getCurrentThreadConn().rollback();
    }
}
  • (IOC关建代码)创建BeanFactory IOC容器 bean工厂
/**
 * @Description: IOC容器 bean工厂
 * @Author: Created by OrangeZh
 * @Date: Created in 2020/9/4 15:15
 */
public class BeanFactory {

    //外部配置文件配置信息
    private static Properties properties = new Properties();

    private static final String classpath = BeanFactory.class.getResource("/").getPath();

    //bean定义Map 处理存放bean的基本信息
    private static Map<String, Class<?>> beanDefinitionMap = new ConcurrentHashMap<>();

    //缓存bean 容器缓存(单例缓存池)
    private static ConcurrentHashMap<String, Object> beanMap = new ConcurrentHashMap<>();

    //扫描到的所有类
    private static List<Class<?>> classList = new ArrayList<>();

    static {
        initIoc();
    }

    /**
     * 初始化容器
     * 1、获取配置文件配置内容
     * 2、配置类(AppConfig)解析
     * 3、扫描包下的所有类
     * 4、遍历所有类,并放入到beanDefinitionMap中
     * 5、实例化并初始化所有bean
     */
    private static void initIoc() {
        try {
            //1、获取配置文件配置内容
            properties = getProperties("jdbc.properties");

            //2、配置类解析
            Class<?> configClass = AppConfig.class;
            String configBeanName = Introspector.decapitalize(configClass.getSimpleName());
            beanDefinitionMap.put(configBeanName, configClass);

            String[] scanPackages = configClass.getAnnotation(ComponentScan.class).value();

            //3、加载包下的所有类
            if (scanPackages.length > 0) {
                for (String scanPackage : scanPackages) {
                    getAllClasses(scanPackage, classList);
                }
            } else {
                getAllClasses("", classList);
            }

            //4、遍历所有类,并放入到beanDefinitionMap中
            if (classList.size() > 0) {
                for (Class<?> clazz : classList) {
                    String beanName = Introspector.decapitalize(clazz.getSimpleName());
                    //类注解
                    if (clazz.isAnnotationPresent(Component.class)) {
                        Component annotation = clazz.getAnnotation(Component.class);
                        if (!annotation.value().equals("")) {
                            beanName = annotation.value();
                        } else if (clazz.getInterfaces().length > 0) {
                            beanName = Introspector.decapitalize(clazz.getInterfaces()[0].getSimpleName());
                        }
                    } else if (clazz.isAnnotationPresent(Service.class)) {
                        Service annotation = clazz.getAnnotation(Service.class);
                        if (!annotation.value().equals("")) {
                            beanName = annotation.value();
                        } else if (clazz.getInterfaces().length > 0) {
                            beanName = Introspector.decapitalize(clazz.getInterfaces()[0].getSimpleName());
                        }
                    } else if (clazz.isAnnotationPresent(Repository.class)) {
                        Repository annotation = clazz.getAnnotation(Repository.class);
                        if (!annotation.value().equals("")) {
                            beanName = annotation.value();
                        }
                    } else {
                        continue;
                    }
                    beanDefinitionMap.put(beanName, clazz);
                }
            }

            //5、实例化并初始化所有bean
            //先初始化配置类
            getBean(configBeanName);
            for (String beanName : beanDefinitionMap.keySet()) {
                getBean(beanName);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 创建bean
     * 1、实例化Bean
     * 2、初始化Bean
     *
     * @param beanName
     * @throws Exception
     */
    private static Object doCreateBean(String beanName) throws Exception {
        Object bean = beanMap.get(beanName);
        if (bean != null) {
            return bean;
        }
        createBeanInstance(beanName);
        populateBean(beanName);
        return beanMap.get(beanName);
    }

    /**
     * 实例化Bean
     *
     * @param beanName
     * @throws Exception
     */
    private static void createBeanInstance(String beanName) throws Exception {
        Class<?> clazz = beanDefinitionMap.get(beanName);
        //实例化
        Object bean = clazz.newInstance();
        if (clazz.isAnnotationPresent(Transactional.class)) {
            //转为代理对象
            ProxyFactory proxyFactory = (ProxyFactory) getBean("proxyFactory");
            if (clazz.getInterfaces().length > 0) {
                bean = proxyFactory.getJdkProxy(bean);//代理对象替换原对象
            } else {
                bean = proxyFactory.getCglibProxy(bean);//代理对象替换原对象
            }
        }
        beanMap.put(beanName, bean);
    }

    /**
     * 初始化Bean
     * 解析 @Autowired、@Value、@Transactional等注解
     *
     * @param beanName
     */
    private static void populateBean(String beanName) throws Exception {
        Object bean = getBean(beanName);
        Class<? extends Object> clazz = bean.getClass();
        //自动注入
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field field : declaredFields) {
            Annotation[] annotations = field.getAnnotations();
            for (Annotation annotation : annotations) {
                if (annotation.annotationType().equals(Autowired.class)) {
                    //Autowired autowiredAnno = field.getAnnotation(Autowired.class);
                    //通过属性名称 获取bean
                    Object value = getBean(field.getName());
                    field.setAccessible(true);
                    //给属性赋值
                    field.set(bean, value);
                } else if (annotation.annotationType().equals(Value.class)) {
                    Value valueAnno = field.getAnnotation(Value.class);
                    String value = valueAnno.value();
                    if (value.startsWith("${") && value.endsWith("}")) {
                        value = properties.getProperty(value.split("${")[1].split("}")[0]);
                    }
                    field.setAccessible(true);
                    //给属性赋值
                    field.set(bean, value);
                }
            }
        }

        //方法注解
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            Annotation[] annotations = method.getAnnotations();
            for (Annotation annotation : annotations) {
                if (annotation.annotationType().equals(Transactional.class)) {
                    //转为代理对象
                    ProxyFactory proxyFactory = (ProxyFactory) getBean("proxyFactory");
                    Class<?>[] cl = clazz.getInterfaces();
                    if (clazz.getInterfaces().length > 0) {
                        bean = proxyFactory.getJdkProxy(bean);//代理对象替换原对象
                    } else {
                        bean = proxyFactory.getCglibProxy(bean);//代理对象替换原对象
                    }
                    beanMap.put(beanName, bean);
                } else if (annotation.annotationType().equals(Bean.class)) {
                    Bean beanAnno = method.getAnnotation(Bean.class);
                    Class<?> returnClass = method.getReturnType();
                    String beanName1 = Introspector.decapitalize(returnClass.getSimpleName());
                    if (!beanAnno.value().equals("")) {
                        beanName1 = beanAnno.value();
                    }
                    //获取方法执行返回的对象,返回的就是bean
                    Object beanClass = method.invoke(bean);
                    beanMap.put(beanName1, beanClass);
                }
            }
        }
    }

    /**
     * 获取bean
     *
     * @param beanName
     * @return
     */
    public static Object getBean(String beanName) throws Exception {
        Object bean = beanMap.get(beanName);
        if (bean == null) {
            bean = doCreateBean(beanName);
        }
        return bean;
    }

    /**
     * 获取某个包下的所有类
     *
     * @param classes     存放类的list
     * @param packageName 包名
     * @return
     */
    private static void getAllClasses(String packageName, List<Class<?>> classes) {
        try {
            //将包名转换为路径
            String path = classpath + packageName.replaceAll(".", Matcher.quoteReplacement(File.separator));
            File file = new File(path);
            File[] fileList = file.listFiles();
            if (null != fileList && fileList.length > 0) {
                for (File curFile : fileList) {
                    if (curFile.isFile()) {
                        System.out.println("file is:" + curFile);
                        System.out.println(packageName + "." + curFile.getName().split(".")[0]);
                        Class<?> aClass = Class.forName(packageName + "." + curFile.getName().split(".")[0]);
                        classes.add(aClass);
                    }
                    if (curFile.isDirectory()) {
                        System.out.println("dir is :" + curFile);
                        getAllClasses(packageName + "." + curFile.getName(), classes);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 读取配置文件
     *
     * @return
     */
    private static Properties getProperties(String... files) {
        Properties properties = new Properties();
        try {
            if (files.length > 0) {
                for (String file : files) {
                    InputStream inputStream = BeanFactory.class.getClassLoader().getResourceAsStream(file);
                    InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
                    properties.load(inputStreamReader);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("Get properties is fail!");
        }
        return properties;
    }
  • 项目源码 https://gitee.com/orangezh/OZAnnoIocDemo

下一篇:

OrangeZh:Spring IOC应用及源码分析​zhuanlan.zhihu.com

回到目录:

OrangeZh:拉勾教育:JAVA高薪训练营 学习笔记​zhuanlan.zhihu.com

文章内容输出来源:拉勾教育 Java高薪训练营

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值