手写spring-ioc

spring ioc指的是控制反转,IOC容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。交由Spring容器统一进行管理,从而实现松耦合

包结构

image

执行流程

image

第一步定义三个注解,用于扫描方法

Service注解表示加了此注解的实现类的实例对象交给spring管理

package org.spring.ioc;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Service {
}

RestController注解表示加了此注解的controller可以通过url访问到具体方法并返回json格式的字符串对象

package org.spring.ioc;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface RestController {

}

Autowired注解表示加了此注解的属性由容器提供值(一般为对象)

package org.spring.ioc;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//加在属性上,属性的值由容器提供
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {

}

第二步定义扫描类,在程序启动时将扫描到注解的类实例化放入容器,并处理autowired注解

package org.spring.ioc;

import java.io.File;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;

import com.tedu.mall.RunApp;

//框架的启动类
public class ApplicationContext {
    // 放的是类名
    ArrayList<String> classNameList = new ArrayList<>();
    // 容器
    // userController,对象
    // userServiceImpl,对象
    HashMap<String, Object> container = new HashMap<>();

    public ApplicationContext() throws Throwable {

        classNameList.add("com.tedu.mall.UserController");
        classNameList.add("com.tedu.mall.UserServiceImpl");
        // 创建对象放到容器中
        loadObject();
        System.out.println(container);
        // 处理autowired注解
        autowiredProcess();
    }

    private void loadObject() throws Throwable {
        // 遍历所有的类
        for (String className : classNameList) {

            Class clazz = Class.forName(className);

            // 判断类有没有加@controller或@service
            RestController controller = (RestController) clazz.getAnnotation(RestController.class);
            Service service = (Service) clazz.getAnnotation(Service.class);
            Object object;
            if (controller != null || service != null) {
                object = clazz.newInstance();
                // 得到key
                int begin = className.lastIndexOf(".") + 1;
                // UserController
                className = className.substring(begin);
                // 把首字母变成小写的
                // userController
                String objectName = Character.toLowerCase(className.charAt(0)) + className.substring(1);
                // 创建对象放到容器中
                container.put(objectName, object);
            }
        }
    }
    private void autowiredProcess() throws Throwable {
        // 遍历容器
        for (String key : container.keySet()) {
            // 取到对象,判断对象属性有没有加autowired
            System.out.println("key="+key);
            Object object = container.get(key);
            Class clazz = object.getClass();
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                Autowired autowired = field.getAnnotation(Autowired.class);
                if (autowired != null) {
                    // @autowired
                    // UserService userServiceImpl
                    String objectName = field.getName();

                    // 从容器中找一个对象赋值给属性
                    Object bean = container.get(objectName);

                    field.setAccessible(true);
                    field.set(object, bean);
                }
            }
        }
    }
    public Object getBean(String beanName) {
        return container.get(beanName);
    }
}

第三步定义业务层接口和实现类,定义控制层Controller并通过@Autowired注解向spring容器要一个对象。

UserService

package com.tedu.mall;

public interface UserService {
    public void register();
}

UserServiceImpl

package com.tedu.mall;

import org.spring.ioc.Service;

@Service
public class UserServiceImpl implements UserService{

    @Override
    public void register() {
        System.out.println("register()");
        
    }

}

UserController

package com.tedu.mall;

import org.spring.ioc.Autowired;
import org.spring.ioc.RestController;

@RestController
public class UserController {

    @Autowired
    UserService userServiceImpl;
    
}

第四步定义启动类RunApp,开启扫描,对加了注解的类进行实例化,并访问controller中的属性,看是否赋值。

package com.tedu.mall;

import org.spring.ioc.ApplicationContext;


public class RunApp {

    public static void main(String[] args) throws Throwable{
        //启动框架
        ApplicationContext applicationContext=
                new ApplicationContext();
        UserController userController=(UserController) applicationContext.getBean("userController");

        System.out.println(userController);
        UserService userService=userController.userServiceImpl;
        userService.register();
    }
}

手写spring-aop

本次练习只是实现简单的aop,实则aop的内容很庞大,面向切面编程是一种思想。

包结构

image

执行流程

image

第一步定义四个注解

@After注解表示要在目标方法前执行的方法

package org.spring.aop;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface After {
}

@Before注解表示要在目标方法后执行的方法

package org.spring.aop;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Before {
}

@Aspect注解表示该类是切面类,用于无侵入式扩充目标方法

package org.spring.aop;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Aspect {
}

@Pointcut注解表示该方法是目标方法

package org.spring.aop;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Pointcut {
//切点com.tedu.mall.UserServiceImpl.register
    //调用register(),自动执行TimeAspect中的方法
    String value();
}

第二步定义业务层接口和实现类

Service接口

package com.tedu.mall;

public interface UserService {
    public void register();
}

ServiceImpl实现类

package com.tedu.mall;



public class UserServiceImpl implements UserService{

    @Override
    public void register() {
        System.out.println("UserServiceImpl.register()");
        
    }

}

第三步定义切面类TimeAspect,对目标方法进行扩充

package com.tedu.mall;

import org.spring.aop.After;
import org.spring.aop.Aspect;
import org.spring.aop.Before;
import org.spring.aop.Pointcut;

@Aspect
public class TimeAspect {
    long startTime;
    @Pointcut("com.tedu.mall.UserServiceImpl.register")
    public void pointCut() {}
    
    @Before
    public void doBefore() {
        System.out.println("doBefore()");
        startTime=System.nanoTime();
    }
    
    @After
    public void doAfter() {
        System.out.println("doAfter()");
        System.out.println("time:"+(System.nanoTime()-startTime));
    }
}

第四步定义ApplicationContext类,用于扫描注解并对其方法做相应处理

package org.spring.aop;

import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.HashMap;

import com.tedu.mall.RunApp;
import com.tedu.mall.TimeAspect;
import com.tedu.mall.UserServiceImpl;

//框架的启动类
public class ApplicationContext {
    // 放的是类
    // 容器
    // userController,对象
    // userServiceImpl,对象
    HashMap<String, Object> container = new HashMap<>();

    public ApplicationContext() throws Throwable {
        UserServiceImpl userServiceImpl=new UserServiceImpl();
        container.put("userServiceImpl", userServiceImpl);
        
        TimeAspect timeAspect=new TimeAspect();
        container.put("timeAspect", timeAspect);
    
        

        // 遍历容器中所有的对象
        for (String key : container.keySet()) {
            // 判断这个对象有没有加@Aspect
            Object object = container.get(key);
            Class clazz = object.getClass();
            Aspect aspect = (Aspect) clazz.getAnnotation(Aspect.class);
            if (aspect != null) {
                Object aspectObject = object;
                // 在执行目标类UserServiceImpl的目标方法register时,自动执行timeAspect
                // 找到pointcut,before,after
                String pointcutString = null;
                Method beforeMethod = null;
                Method afterMethod = null;

                // 遍历TimeAspect的所有方法
                Method[] methods = aspectObject.getClass().getDeclaredMethods();
                for (Method method : methods) {
                    Pointcut pointcut = method.getAnnotation(Pointcut.class);
                    Before before = method.getAnnotation(Before.class);
                    After after = method.getAnnotation(After.class);
                    if (pointcut != null) {
                        pointcutString = pointcut.value();
                    }
                    if (before != null) {
                        beforeMethod = method;
                    }
                    if (after != null) {
                        afterMethod = method;
                    }
                }
                // pointcutString=com.tedu.mall.UserServiceImpl.register
                // 得到key userServiceImpl;从容器中找到目标类的对象
                String[] strings = pointcutString.split("\\.");
                String targetObjectkey = strings[strings.length - 2];
                targetObjectkey = Character.toLowerCase(targetObjectkey.charAt(0)) + targetObjectkey.substring(1);
                // 得到目标类对象,创建动态代理对象proxy
                Object targetObject = container.get(targetObjectkey);

                Class[] interfaces = targetObject.getClass().getInterfaces();
                ClassLoader loader = targetObject.getClass().getClassLoader();
                AopHandler aopHandler = new AopHandler(targetObject, beforeMethod, afterMethod, aspectObject);
                Object proxy = Proxy.newProxyInstance(loader, interfaces, aopHandler);

                // 容器中userServiceimpl原先的对象是用反射创建的对象,改成proxy
                // userServiceImpl,
                container.put(targetObjectkey, proxy);
                // 程序员从容器中取对象,取到的是proxy,proxy.register()
            }
        }

    
    }

    

    class AopHandler implements InvocationHandler {
        Object targetObject;// UserServiceImpl
        Method beforeMethod;
        Method afterMethod;
        Object aspectObject;

        public AopHandler(Object targetObject, Method beforeMethod, Method afterMethod, Object aspectObject) {
            super();
            this.targetObject = targetObject;
            this.beforeMethod = beforeMethod;
            this.afterMethod = afterMethod;
            this.aspectObject = aspectObject;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            // 调用切面的before
            if (beforeMethod != null)
                beforeMethod.invoke(aspectObject);
            // 调用目标方法UserServiceImpl.register
            method.invoke(targetObject, args);
            // 调用切面的after
            if (afterMethod != null)
                afterMethod.invoke(aspectObject);
            return null;
        }
    }
    public Object getBean(String beanName) {
        return container.get(beanName);
    }
}

第五步定义启动类RunApp,启动扫描类,并测试。

package com.tedu.mall;

import org.spring.aop.ApplicationContext;
public class RunApp {

    public static void main(String[] args) throws Throwable {
        // 启动框架
        ApplicationContext applicationContext = new ApplicationContext();
        UserService userService = (UserService) applicationContext.getBean("userServiceImpl");
        System.out.println(userService.getClass().getName());
        userService.register();
    }
}

禾白少二
57 声望26 粉丝