spring IOC/AOP实现

创建springboot

创建对应文件

dao、service包下的文件用于实现ioc和di的测试类
bean下的是读取上下文扫描自定义注解
anno下是自定义@Bean和@Autowired 的注解
/**
 * bean管理注解模拟@Service注解
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DemoBean {
    
}
/**
 * 依赖注入模拟@Autowired
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DemoDi {
    
}
/*
* 上下文接口
*/
public interface ApplicationContext {

    Object getBean(Class clazz);

}

public class IOCApplicationContext implements ApplicationContext {

    private Map<Class, Object> beanMap = new HashMap<>();
    private static String rootPath = null;

    @Override
    public Object getBean(Class clazz) {
        return beanMap.get(clazz);
    }

    /**
     * 创建有参构造,设置扫描规则
     * 当前包以及子包,哪些类有@DemoBean注解,使用反射实例化并添加到beanMap中
     */
    public IOCApplicationContext(String scanPackage) {
        if (StringUtils.isEmpty(scanPackage)) {
            throw new RuntimeException("包路径不能为空");
        }
        try {
            // 1、将包路径转换成文件路径(com.learn.boot.ioc --->com/learn/boot/ioc)
            String packagePath = scanPackage.replaceAll("\\.", "\\\\");
            // 2、获取绝对路径
            Enumeration<URL> resources = Thread.currentThread().getContextClassLoader().getResources(packagePath);
            while (resources.hasMoreElements()) {
                URL url = resources.nextElement();
                // 将url 转码
                String path = URLDecoder.decode(url.getFile(), "UTF-8");
                if (rootPath == null) {
                    rootPath = path.substring(0, path.length() - packagePath.length());
                }
                // 包扫描
                scanBean(new File(path));
            }
            scanDi();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void scanDi() {
        // 遍历beanMap
        beanMap.forEach((k, v) -> {
            Class<?> clazz = v.getClass();
            // 获取所有属性
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                // 判断属性上是否存在@DemoDi注解
                DemoDi annotation = field.getAnnotation(DemoDi.class);
                if (null != annotation) {
                    // 如果是私有属性,需要开启设置
                    field.setAccessible(true);
                    // 如果有,则匹配设置
                    try {
                        // v 当前对象,要设置的值
                        field.set(v,beanMap.get(field.getType()));
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }

    /**
     * 包扫描
     *
     * @param file
     */
    private void scanBean(File file) throws Exception {
        // 判断是否是文件夹.否,直接返回
        if (file.isDirectory()) {
            // 获取文件夹内容
            File[] files = file.listFiles();
            // 为空直接返回
            if (files == null || files.length == 0) {
                return;
            }
            // 不为空遍历数据
            for (int i = 0; i < files.length; i++) {
                File f = files[i];
                // 如果还存在内容,递归获取数据
                if (f.isDirectory()) {
                    // 递归继续获取
                    scanBean(f);
                } else {
                    // 如果是文件则判断是否是class,如果是则将\转换为.,并去掉.class
                    String absolutePath = f.getAbsolutePath();
                    if (absolutePath.endsWith(".class")) {
                        String pathClass = absolutePath.substring(rootPath.length() - 1);
                        // 替换并截取,得到文件路径:com.learn.boot.ioc.service.impl.DemoServiceImpl
                        String className = pathClass.replaceAll("\\\\", "\\.").replace(".class", "");
                        // 通过反射获取对象
                        Class<?> clazz = Class.forName(className);
                        // 判断是否是接口,否则需要实例化
                        if (!clazz.isInterface()) {
                            // 是则判断存在@DemoBean注解
                            DemoBean annotation = clazz.getAnnotation(DemoBean.class);
                            // 如果annotation !=  null,当前类上有注解
                            if (annotation != null) {
                                // 实例化
                                Object o = clazz.getConstructor().newInstance();
                                // 判断当前类是否实现接口,有则使用接口的Class作为key
                                int length = clazz.getInterfaces().length;
                                if (length > 0) {
                                    // 如果有实现多个接口,则使用接口的Class作为key
                                    Class<?>[] interfaces = clazz.getInterfaces();
                                    for (Class<?> anInterface : interfaces) {
                                        // 存在则添加到Map中
                                        beanMap.put(anInterface, o);
                                    }
                                } else {
                                    // 没有接口则使用自己的class
                                    beanMap.put(clazz, o);
                                }
                            }
                        }
                    }
                }
            }
        }
    }


    public static void main(String[] args) {
        IOCApplicationContext iocApplicationContext = new IOCApplicationContext("com.learn.boot.ioc");
        IDemoService bean = (IDemoService) iocApplicationContext.getBean(IDemoService.class);
        bean.add();
    }
}
@DemoBean
public class DemoDaoImpl implements IDemoDao {
    @Override
    public void test() {
        System.out.println("DemoDaoImpl.test.........");
    }
}
public interface IDemoDao {

    void test();

}
@DemoBean
public class DemoServiceImpl implements IDemoService {

    @DemoDi
    private IDemoDao demoDao;


    @Override
    public void add() {
        System.out.println("DemoServiceImpl.add......");
        demoDao.test();
    }
}
public interface IDemoService {

    void add();

}

在实现springIOC Di的过程中主要是反射,通过对应的包路径进行扫描添加到容器中,在使用的过程中可直接使用。

动态代理-JDK的动态代理

动态代理可批量完成统一业务功能,且解耦
动态代理JDK的动态代理和Cglib的动态代理
有接口使用JDK动态代理,代理对象和目标对象实现同样的接口
代理对象返回的是接口
如果没有接口,使用的是cglib动态代理
代理对象返回的是指定类
准备:
两个接口,对应实现类,代理类、测试类
public interface ProxyService {

   void create();

   void update();

   void query();

   void delete();
}
public class ProxyServiceImpl implements ProxyService {
    @Override
    public void create() {
        System.out.println("UserServiceImpl.create.......");
    }

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

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

    @Override
    public void delete() {
        System.out.println("UserServiceImpl.delete.......");
    }
}
public interface UserDemoService {

    void create();

    void update();

    void query();

    void delete();

}

public class UserDemoServiceImpl implements UserDemoService {
    @Override
    public void create() {
        System.out.println("--------------UserDemoServiceImpl.create---");
    }

    @Override
    public void update() {
        System.out.println("--------------UserDemoServiceImpl.create---");
    }

    @Override
    public void query() {
        System.out.println("--------------UserDemoServiceImpl.create---");
    }

    @Override
    public void delete() {
        System.out.println("--------------UserDemoServiceImpl.create---");
    }
}
public class ServiceProxy {
    // 针对所有类
    private Object target;
    // 有参构造初始化
    public ServiceProxy(Object target) {
        this.target = target;
    }

    /**
     * 返回代理对象,模拟环绕通知
     * @return
     */
    public Object getProxy(){
        // ClassLoader loader 加载动态生成代理类的类加载器(目标类加载器)
        // Class<?>[] interfaces  目标对象实现的所有接口
        // InvocationHandler h 调用处理器
        Class<?> clazz = target.getClass();
        System.out.println("----clazz:"+clazz);
        ClassLoader classLoader = clazz.getClassLoader();
        System.out.println("----classLoader:"+classLoader);
        Class<?>[] interfaces = clazz.getInterfaces();
        System.out.println("----interfaces:"+interfaces);
        InvocationHandler handler = (proxy, method, args) ->{
            String name = method.getName();
            System.out.println("【日志】-"+name+"-【调用前执行】-------"+args);
            Object invoke = method.invoke(target, args);
            System.out.println("【日志】-"+name+"-【调用后执行】-------"+args);
            return invoke;
        };
        Object o = Proxy.newProxyInstance(classLoader, interfaces, handler);
        return o;
    }
}

测试:

public class TestProxy {

    public static void main(String[] args){
        ServiceProxy serviceProxy = new ServiceProxy(new ProxyServiceImpl());
        ServiceProxy userProxy = new ServiceProxy(new UserDemoServiceImpl());
        ProxyService proxy = (ProxyService) serviceProxy.getProxy();
        proxy.create();
        UserDemoService proxy1 =(UserDemoService) userProxy.getProxy();
        proxy1.create();

    }

}

结果:

动态代理-cglib的动态代理

// 创建拦截器实现MethodInterceptor
public class ProxyInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("------cglib----------start-----");
        Object invoke = methodProxy.invokeSuper(o, objects);
        System.out.println("------cglib----------end-----");
        return invoke;
    }
}
// 要代理的目标对象
public class UserDemoServiceImpl {
    public void create() {
        System.out.println("--------------UserDemoServiceImpl.create---");
    }

    public void update() {
        System.out.println("--------------UserDemoServiceImpl.create---");
    }

    public void query() {
        System.out.println("--------------UserDemoServiceImpl.create---");
    }

    public void delete() {
        System.out.println("--------------UserDemoServiceImpl.create---");
    }
}
// 测试
public class TestProxy {

    public static void main(String[] args){
//        ServiceProxy serviceProxy = new ServiceProxy(new ProxyServiceImpl());
//        ProxyService proxy = (ProxyService) serviceProxy.getProxy();
//        proxy.create();
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(UserDemoServiceImpl.class);
        enhancer.setCallback(new ProxyInterceptor());
        UserDemoServiceImpl o = (UserDemoServiceImpl) enhancer.create();
        o.create();
    }

}

结果

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值