JAVA实现Spring IOC 容器技术和AOP切面编程技术

Spring-IOC和AOP简介 将那些与业务无关的,但是却是业务模块需要调用的事务,日志等模块封装起来,减少重复代码,降低了耦合性,利于扩展和维护,基于动态代理实现,若是代理的对象实现了某个接口,springAOP会使用JDK动态代理创建代理对象,如果没有实现接口,使用CGLIB动态代理生成被代理对象的子类作为代理。基础的开源开发框架,主要用来开发java应用,预留了许多扩展,其中一些扩展是针对构建J2EE平台的web应用,spring管理对象的整个生命周期,可直接从spring中获取对象,不需要手动创建。切面太多时选择AspectJ。 阅读详情

Spring IOC介绍

spring ioc技术在目前来说已经是非常成熟的JAVA容器技术了,使用也是非常广泛,可以说目前市场上用了spring,那么IOC是其最核心的部分;IOC全称叫Inversion of Control,是控制反转的意思,平时我们编写java代码时,一般需要调用某个类对象的方法时候,通常都是通过new 或者通过类路径反射出来类的对象而进行调用,而使用完毕过后JVM进行回收,而Spring IOC是将我们的所有对象交给它来管理,它来管理这些对象的生命周期,而我们需要使用时,只需要告诉spring,spring将我们需要的对象拿给我们;通俗的将就是我们平时new的时候,熟悉JVM的同学都知道,在new的时候JVM在堆上会给我们分配空间,首先要计算,到底这个对象放在堆上的那个区 ,在进行分配,如果空间不足,还需要进行GC,而spring的对象是在容器中进行管理的,就大大节约了分配对象空间而浪费的时间;spring出来了已经有好些年了,使用率也是最高的,这边我就不在赘述spring ioc的理念了,相信大多数人都是非常清楚。

spring AOP

spring aop也是sprig的一大特性,也算是对JAVA OOP的一个补充,AOP的字面意思就是Aspect Oriented Programming,面向切面编程;什么是切面编程,我这边也不说官方的那些理念,我的理解就是切面就是java 中的代理模式的一个升级,什么是代理模式,就是我们经常会做许多的事儿,而这些事儿都有一些共同点;但是我们如果像传统的做法没做完或者做前时都去把这些事儿都给做了,那么就会出现做许多重复的事情,所以首先我们在设计程序或者服务的时候就需要把这些共同的事情都给抽离出来,交给一个叫”代理的人”去做,代理的人负责把这些事儿都给我们做了,而我们主人只需要做我们关心的那部分事情,我不需要关心这个事情的链条的分支,我只关心我主链条上我必须做的事情,所以这就是AOP的概念,我们把我们不关心但是和主业务流程无关的那部分事情抽离出来交给AOP切面去做;其实JAVA的动态代理模式也是AOP的核心理念;我这边也不做过多的赘述,有兴趣的朋友可以去翻看下spring的源码,好好了解下spring的精髓。

自定义spring ioc容器和AOP切面技术

上面我大概介绍了下spring ioc技术和aop切面技术,那么我这篇文章不是来介绍spring的,而是通过spring ioc容器技术的理念和对aop的技术的理念来做一个简易版的ioc和aop技术框架;如果做的不好的地方大神请指教,我的jdk版本是1.8,开发平台是Eclipse 2019版本,这套ioc容器技术和aop切面其实也可以用于无法接入spring 框架技术的平台使用,但是由于自己平时工作比较忙,我就花了2个下午自己写来看看,一是想更深的熟悉ioc容器技术和aop,二是可能以后自己所在的平台无法接入spring框架,那么这是一个不错的选择,希望我们能够一起学习进步;
代码工程图:
代码工程图
其中
AbstractScanRegisterAnnon.java是父类的扫描指定注解类;
ScanIocHandler.java是配置扫描Component注解类的处理器
包下面的aspect和ioc是对aop和ioc的实现

实现过程

创建注解

我这边建了大概有9个注解,分别如下:
Component注解(类似于spring中的Component注解):

import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Documented
@Retention(RUNTIME)
@Target(TYPE)
public @interface Component {
	
	String name() default "";
	
	enum BEAN_TYPE{
		/**
		 * 单例,容器初始化时,创建实例放入容器,在系统的生命周期之内只存在一个单例对象
		 */
		singleton,
		/**
		 * 容器初始化时无需创建对象,在每次调用时创建
		 */
		prototype 
	}
	BEAN_TYPE beanType() default BEAN_TYPE.singleton;
	

}

AutoWired依赖注入的注解:

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Documented
@Retention(RUNTIME)
@Target(FIELD)
public @interface AutoWired {
	//这边加了value,是代表可以通过beanName获取容器bean对象
	String value() default "";

}

Bean注解(用于方法上,将方法的返回对象作为一个新的Bean注入容器):

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

@Documented
@Retention(RUNTIME)
@Target(ElementType.METHOD)
public @interface Bean {
	/**
	 * 一般使用方法的名字作为Bean,当设置了name属性过后,以设置的为准
	 * method name:propertys
	 * description:
	 * create time:2020年5月19日
	 */
	String name() default "";
	/**
	 * 初始化BEAN初始化的属性
	 * method name:propertys
	 * description:
	 * create time:2020年5月19日
	 */
	Property [] propertys() default {};

Property 注解(主要用于在@Bean上有初始化参数的配置)

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Documented
@Retention(RUNTIME)
@Target(ANNOTATION_TYPE)
public @interface Property {
	
	String name() default "";
	String value() default "";

}

Aspect注解(用来标识是切面)



import static java.lang.annotation.RetentionPolicy.RUNTIME;

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

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

}

Pointcut注解(切面扫描的规则注解)



import static java.lang.annotation.RetentionPolicy.RUNTIME;

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

@Documented
@Retention(RUNTIME)
@Target(ElementType.METHOD)
public @interface Pointcut {

	String execution();
}

BeforeRuning注解(执行前调用)


import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Documented
@Retention(RUNTIME)
@Target(METHOD)
public @interface BeforeRuning {

}

AfterReturning 在执行成功后调用:


import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
public @interface AfterReturning {

}

AfterThrowing 在执行出现异常时调用:

import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
public @interface AfterThrowing {

}

创建扫描注解父类


import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URI;
import java.net.URL;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

/**
 * 
 * 文件名:AbstractScanRegisterAnnon.java  说 明:
 * 扫描系统注册的注解处理器 创 建 人: baiml 创 建 日 期:2019年12月3日 修 改 人: 修 改 日 期:
 */
public abstract class AbstractScanRegisterAnnon {
	private Logger logger = LoggerFactory.getLogger(AbstractScanRegisterAnnon.class);

	/**
	 * 
	 * 方 法 名:getClassLoader 
	 * 
	 * @return 返 回 类 型:ClassLoader 说 明:获取类加载器 创 建 人:baiml 创 建 日 期:2019年12月3日 修 改 人:
	 *         修 改 日 期:
	 */
	protected abstract ClassLoader getClassLoader();

	/**
	 * 
	 * 方 法 名:getScanPackage 
	 * 
	 * @return 返 回 类 型:String 说 明:获取扫描的注解包策略 创 建 人:baiml 创 建 日 期:2019年12月3日 修 改 人: 修
	 *         改 日 期:
	 */
	protected abstract String getScanPackage();

	/**
	 * 
	 * 方 法 名:isAddClass 
	 * 
	 * @param clzz
	 * @return 返 回 类 型:boolean 说 明:是否可以添加扫描到的类 创 建 人:baiml 创 建 日 期:2019年12月3日 修 改 人:
	 *         修 改 日 期:
	 */
	protected abstract boolean isAddClass(Class<? extends Object> clzz);

	/**
	 * 
	 * 方 法 名:isAgreeCheck 
	 * 
	 * @param packName
	 * @return 返 回 类 型:boolean 说 明:是否通过校验 创 建 人:baiml 创 建 日 期:2019年12月3日 修 改 人: 修 改
	 *         日 期:
	 */
	protected abstract boolean isAgreeCheck(String packName);
	/**
	 * 
	 * 方 法 名:checkPatten
	 *
	 * @param packName
	 * @return              
	 * 返 回 类 型:       boolean
	 * 说 明:               检查匹配
	 * 创 建 人:          baiml
	 * 创 建 日 期:       2019年12月23日
	 * 修 改 人: 
	 * 修 改 日 期:
	 */
	protected abstract boolean checkPatten(String packName);

	/**
	 * 
	 * 方 法 名:scanRegisterClass 
	 * 
	 * @return
	 * @throws Exception 返 回 类 型:List<Class<? extends Object>> 说 明:扫描 创 建 人:baiml 创
	 *                   建 日 期:2019年12月3日 修 改 人: 修 改 日 期:
	 */
	public List<Class<? extends Object>> scanRegisterClass() {
		List<Class<? extends Object>> result = Lists.newArrayList();
		String packageName = getScanPackage();
		if (logger.isDebugEnabled()) {
			logger.debug("AbstractScanRegisterAnnon.scanRegisterClass 扫包开始 packageName={}...", packageName);
		}
		try {
			scanPackage(packageName, result);
		} catch (Exception e) {
			e.printStackTrace();
		}
		if (logger.isDebugEnabled()) {
			logger.debug("AbstractScanRegisterAnnon.scanRegisterClass 扫包结束packageName={}...", packageName);
		}
		return result;
	}

	private void scanPackage(String classpack, List<Class<? extends Object>> list) throws Exception {
		URL url = getClassLoader().getResource(classpack.replace(".", "/"));
		String protocol = url.getProtocol();
		if (protocol.equals("file")) {
			// 本地class
			scanLocalClass(classpack, url.toURI(), list);
		} else if (protocol.equals("jar")) {
			// jar扫描
			scanLocalJar(classpack, list);
		}
	}

	private void scanLocalJar(String classpack, List<Class<? extends Object>> list) {
		String pathName = classpack.replace(".", "/");
		try {
			Enumeration<URL> dir = Thread.currentThread().getContextClassLoader().getResources(pathName);
			List<JarFile> arrayList = Lists.newCopyOnWriteArrayList();
			while (dir.hasMoreElements()) {
				URL u = dir.nextElement();
				String path = u.getPath();
				if(path.indexOf(".jar") != -1 ) {
					JarURLConnection c = (JarURLConnection) u.openConnection();
					JarFile f = c.getJarFile();
					arrayList.add(f);
				}
			}
			// 去重,不知道为什么系统启动过后自动加载,distinct没有效果,而从调用来执行,是有效果的
			arrayList = arrayList.stream().distinct().collect(Collectors.toList());
			Map<String, String> co = Maps.newConcurrentMap();
			arrayList.forEach(item -> {
				if (!co.containsKey(item.getName())) {
					scanJarClass(item, pathName, list);
					co.put(item.getName(), "1");
				}

			});
		} catch (IOException e) {
			e.printStackTrace();
			if (logger.isErrorEnabled()) {
				logger.error("未找到jar的资源");
			}
		}
	}

	private void scanJarClass(JarFile jarFile, String pathName, List<Class<? extends Object>> list) {
		Enumeration<JarEntry> jarEnties = jarFile.entries();
		while (jarEnties.hasMoreElements()) {
			JarEntry jarEntry = jarEnties.nextElement();
			String jarEntryName = jarEntry.getName();
			if (jarEntryName.contains(pathName) && !jarEntryName.equals(pathName + "/")) {
				if (jarEntry.isDirectory()) {
					continue;
				}
				if (isAgreeCheck(jarEntry.getName())) {
					try {
						Class<? extends Object> clzz = getClassLoader().loadClass(jarEntry.getName().replace("/", ".").replace(".class", ""));
						if (isAddClass(clzz)) {
							list.add(clzz);
						}
					} catch (ClassNotFoundException e) {
						e.printStackTrace();
					}
				}
			}
		}
	}

	private void scanLocalClass(String classpack, URI url, List<Class<? extends Object>> list) {
		File file = new File(url);
		file.listFiles(new FileFilter() {
			@Override
			public boolean accept(File f) {
				String filename = f.getName();
				if (f.isDirectory()) {
					try {
						scanPackage(classpack + "." + filename, list);
					} catch (Exception e) {
						e.printStackTrace();
					}
				} else {
					if (isAgreeCheck(f.getAbsolutePath())) {
						try {
							Class<? extends Object> clzz = getClassLoader().loadClass(classpack + "." + filename.replace(".class", ""));
							if (isAddClass(clzz)) {
								list.add(clzz);
							}
						} catch (ClassNotFoundException e) {
							e.printStackTrace();
						}

					}
				}
				return false;
			}
		});
	}

}

父类定义抽象方法,由子类来提供扫描的包名的规则和是否符合子类的需求来决定是否添加到扫描的列表中,就是说你想实现怎样的规则和是否要添加到扫描列表中由子类来决定;

ioc扫描子类:

public class ScanIocHandler extends AbstractScanRegisterAnnon {
	private Logger logger = LoggerFactory.getLogger(ScanIocHandler.class);
	/**
	 * 包策略
	 */
	public final String packageName = "com.icitic.unionpay";
	/**
	 * 匹配类名,只有已patten结尾的类才能被扫到 "" 代表所有包
	 */
	public final String patten = "";
	@Override
	protected ClassLoader getClassLoader() {
		return ScanIocHandler.class.getClassLoader();
	}

	@Override
	protected String getScanPackage() {
		return packageName;
	}

	@Override
	protected boolean isAddClass(Class<? extends Object> clzz) {
		boolean isExecute = false;
		if (clzz.isAnnotationPresent(Component.class)) {
			isExecute = true;
			if (logger.isDebugEnabled()) {
				logger.debug("ScanIocHandler.isAddClass 扫描到Component容器类:{}", clzz.getName());
			}
		}
		return isExecute;

	}

	@Override
	protected boolean isAgreeCheck(String packName) {
		boolean isExecute = false;
		if (packName.endsWith(".class")) {
			isExecute = checkPatten(packName);
		}
		return isExecute;
	}

	@Override
	protected boolean checkPatten(String packName) {
		return true;
	}

创建IOC相关的类

FactoryBean Bean的信息对象:

public class FactoryBean {
	/**
	 * Bean名称
	 */
	private String beanName;
	/**
	 * Bean对象
	 */
	private Object beanInstance;
	/**
	 * Bean所在类
	 */
	private Class<? extends Object> beanClzz;
	/**
	 * Bean的注解
	 */
	private Component component;
	
	public String getBeanName() {
		return beanName;
	}
	public void setBeanName(String beanName) {
		this.beanName = beanName;
	}
	public Object getBeanInstance() {
		return beanInstance;
	}
	public void setBeanInstance(Object beanInstance) {
		this.beanInstance = beanInstance;
	}
	public Class<? extends Object> getBeanClzz() {
		return beanClzz;
	}
	public void setBeanClzz(Class<? extends Object> beanClzz) {
		this.beanClzz = beanClzz;
	}
	public Component getComponent() {
		return component;
	}
	public void setComponent(Component component) {
		this.component = component;
	}
	@Override
	public String toString() {
		return "FactoryBean [beanName=" + beanName + ", beanInstance=" + beanInstance + ", beanClzz=" + beanClzz
				+ ", component=" + component + "]";
	}

IOCFactory,这个类是整个框架 核心,我这边也只是试着写,没有特别的去设计,分的很细,所以都ioc的核心都写在这里:

public class IOCFactory  extends AspectFactory {
	
	/**
	 * bean容器
	 */
	protected static Map<String,FactoryBean> beanFactory = Maps.newConcurrentMap();
	
	/**
	 * Integer函数转换器
	 */
	private Function<String, Integer> functionInteger = Integer::valueOf;
	/**
	 * BigDecimal函数转化器
	 */
	private Function<String,BigDecimal> functionBigdecimal = BigDecimal::new;
	/**
	 * Double函数转化器
	 */
	private Function<String,Double> functionDouble = Double::valueOf;
	/**
	 * Float函数转化器
	 */
	private Function<String,Float> functionFloat = Float::valueOf;
	
	private List<AspectInfo> aspectInfo;
	
	
	
	protected synchronized  void init() throws Exception {
		AbstractScanRegisterAnnon scan = new ScanIocHandler();
		List<Class<? extends Object>> list = scan.scanRegisterClass();
		if(list != null && list.size() > 0 ) {
			/**
			 * 1.加载切面信息 
			 */
			setAspectInfo();
			/**
			 * 2.对注册了component的类注册为容器Bean
			 */
			newInstance(list);
			/**
			 * 3.对新注册的Bean进行容器化
			 * 
			 */
			findBean();
			/**
			 * 4.对配置了autoWired的注解进行依赖注入
			 */
			autoWired();
			
		}
	}
	
	private  void findBean() throws Exception {
		String [] keys = beanFactory.keySet().toArray(new String[beanFactory.size()]);
		Map<String,FactoryBean> methodBean = Maps.newConcurrentMap();
		for(String key : keys) {
			FactoryBean fbean = beanFactory.get(key);
			Class<? extends Object> clzz = fbean.getBeanClzz();
			Method [] methods = clzz.getDeclaredMethods();
			for(Method method : methods) {
				boolean isAccessable = method.isAccessible();
				method.setAccessible(true);
				if(method.isAnnotationPresent(Bean.class)) {
					/**
					 * 找到一个Bean,将其注册为容器的Bean
					 */
					FactoryBean newBean = registerBean(method,fbean);
					if(newBean != null ) {
						methodBean.put(newBean.getBeanName(), newBean);
					}
				}
				method.setAccessible(isAccessable);
			}
			/**
			 * 将新找到的Bean注册到容器中
			 */
			if(!methodBean.isEmpty()) {
				beanFactory.putAll(methodBean);
			}
		}
	}
	
	
	private  FactoryBean registerBean(Method method,FactoryBean factoryBean ) throws Exception {
		FactoryBean fbean = null;
		Bean bean = method.getAnnotation(Bean.class);
		/**
		 * 这边注册的bean默认没有参数,默认空参数的方法,Bean的默认都是单例
		 */
		Object object = method.invoke(getObject(factoryBean), new Object[0]);
		if(object != null ) {
			/**
			 * 判断Bean是否有初始化的参数,有的话进行初始化
			 */
			initBeanProperty(object, bean);
			fbean = new FactoryBean();
			fbean.setBeanClzz(object.getClass());
			fbean.setBeanInstance(object);
			fbean.setBeanName(getBeanNameByMethod(method, bean));
			fbean.setComponent(factoryBean.getComponent());
		}
		return fbean;
	}
	
	private String getBeanNameByMethod(Method method,Bean bean) {
		String name = bean.name();
		if(StringUtils.isEmpty(name)) {
			name = method.getName();
		}
		return name;
	}
	/**
	 * 
	 * method name:initBeanProperty
	 * description:初始化
	 * @param object
	 * @param bean
	 * return_type:void
	 * creator:baiml
	 * create time:2020年5月19日
	 * modifier: 
	 * modify time:
	 * @throws SecurityException 
	 * @throws NoSuchFieldException 
	 * @throws IllegalAccessException 
	 * @throws IllegalArgumentException 
	 */
	private void initBeanProperty(Object object,Bean bean) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
		Property [] ps = bean.propertys();
		if (ps != null && ps.length > 0) {
			Class<? extends Object> clzz = object.getClass();
			for (Property property : ps) {
				// name就是对象的属性
				String name = property.name();
				String value = property.value();
				if (StringUtils.isNotEmpty(value)) {
					// 只有配置了并且值不为空的情况下才能进行初始化赋值
					Field field = clzz.getDeclaredField(name);
					boolean isAccessable = field.isAccessible();
					field.setAccessible(true);
                     /**
                      * 设置值
                      */
					setValue(field, object, value);
					field.setAccessible(isAccessable);
				}
			}
		}
	}
	
	private void setValue(Field field,Object instance,String value) throws IllegalArgumentException, IllegalAccessException {
		Class<?> filedType = field.getType();
		if (filedType.equals(String.class) || filedType == String.class) {
			field.set(instance, value);
		}
		if (filedType.equals(BigDecimal.class) || filedType == BigDecimal.class) {
			field.set(instance, functionBigdecimal.apply(value));
		}
		if (filedType.equals(Integer.class) || filedType == Integer.class) {
			field.set(instance, functionInteger.apply(value));
		}
		if (filedType.equals(Double.class) || filedType == Double.class) {
			field.set(instance, functionDouble.apply(value));
		}
		if (filedType.equals(Float.class) || filedType == Float.class) {
			field.set(instance, functionFloat.apply(value));
		}
	}
	
	
	
	
	private  void newInstance(List<Class<? extends Object>> list) throws Exception{
		for(Class<? extends Object> clzz : list) {
			//取得所有的继承接口
			Class<?>[] interfaces = clzz.getInterfaces();
			//获取BEAN的名字
			String beanName = getBeanName(clzz,interfaces);
			Object obj = getInstance(clzz);
			FactoryBean bean = new FactoryBean();
			bean.setBeanName(beanName);
			bean.setBeanClzz(clzz);
			bean.setBeanInstance(obj);
			bean.setComponent(clzz.getAnnotation(Component.class));
			beanFactory.put(beanName, bean);
		}
	}
	/**
	 * 
	 * method name:getBeanName
	 * description:获取BEAN名称
	 * @param objClzz
	 * @param interfaces
	 * @return
	 * return_type:String
	 * creator:baiml
	 * create time:2020年5月19日
	 * modifier: 
	 * modify time:
	 */
	private  String getBeanName(Class<?> objClzz,Class<?>[] interfaces) {
		String beanName = null;
		Component component = objClzz.getAnnotation(Component.class);
		beanName = component.name();
		if(StringUtils.isEmpty(beanName)) {
			if(interfaces != null && interfaces.length > 0 ) {
				Class<?> clzz = interfaces[0];
				String clzzSimpleName = clzz.getSimpleName();
				beanName = clzzSimpleName.substring(0,1).toLowerCase() + clzzSimpleName.substring(1);
			}else {
				String clzzSimpleName = objClzz.getSimpleName();
				beanName = clzzSimpleName.substring(0,1).toLowerCase() + clzzSimpleName.substring(1);
			}
		}
		return beanName;
	}
	
	private  Object getInstance(Class<? extends Object> clzz) throws Exception {
		Object object = null;
		Component component = clzz.getAnnotation(Component.class);
		Component.BEAN_TYPE beanType = component.beanType();
		if(beanType.equals(Component.BEAN_TYPE.singleton)) {
			/**
			 * 判断是否有切面
			 */
			object = getInstanceByAspect(clzz);
		}
		return object;
		
	}
	
	protected Object getInstanceByAspect(Class<? extends Object> clzz) throws Exception {
		Object object = null;
		if (this.aspectInfo != null && aspectInfo.size() > 0) {
			String classname = clzz.getName();
			List<AspectInfo> infolist = aspectInfo.stream().filter(item -> {
				Pattern p = Pattern.compile(item.getPointcut().execution());
				Matcher m = p.matcher(classname);
				return m.matches();
			}).collect(Collectors.toList());
			if (infolist != null && infolist.size() > 0) {
				AspectInfo info = infolist.get(0);
				object = getProxyService(clzz,info);
			}else{
				object = clzz.newInstance();
			}
		}else {
			object = clzz.newInstance();
		}
		return object;
	}
	
	public  Object getProxyService(Class<? extends Object> clzz,AspectInfo info) throws Exception {
		ClassLoader loader = getClass().getClassLoader();
		ContainerProxy proxy = new ContainerProxy();
		proxy.setAfterMethod(info.getAfterMethod());
		proxy.setAfterTrxMethod(info.getAfterTrxMethod());
		proxy.setBeforeMethod(info.getBeforeMethod());
		proxy.setAspectObject(getAspectObject(info));
		Object trueObject = clzz.newInstance();
		proxy.setObject(trueObject);//真正代理的对象
		info.setTrueProxy(trueObject);
		return  Proxy.newProxyInstance(loader, clzz.getInterfaces(), proxy);
	}
	
	public  Object getAspectObject(AspectInfo info) throws Exception {
		Object result = null;
		Class<? extends Object> clzz = info.getAspectClzz();
		String clname = clzz.getSimpleName();
		String beanName = clname.substring(0,1).toLowerCase() + clname.substring(1);
		if(clzz.isAnnotationPresent(Component.class)) {
			Component com = clzz.getAnnotation(Component.class);
			if(StringUtils.isNotEmpty(com.name())) {
				beanName = com.name();
			}
		}
		FactoryBean fbean = beanFactory.get(beanName);
		if(fbean != null ) {
			result = getObject(fbean);
		}else {
			result = clzz.newInstance();
		}
		return result;
	}
	
	private  void autoWired() throws Exception{
		String [] keys = beanFactory.keySet().toArray(new String[beanFactory.size()]);
		for(String key : keys) {
			FactoryBean fbean = beanFactory.get(key);
			autoSet(fbean); 
		}
	}
	
	

	/**
	 * 
	 * method name:autoSet
	 * description:单例的Bean的初始化
	 * @param fbean
	 * @throws Exception
	 * return_type:void
	 * creator:baiml
	 * create time:2020年5月19日
	 * modifier: 
	 * modify time:
	 */
	private  void autoSet(FactoryBean fbean) throws Exception {
		Object beanInstance = fbean.getBeanInstance();
		if (beanInstance != null) {
			denpence(beanInstance);
		}
	}
	/**
	 * 
	 * method name:autoSetByPropto
	 * description:对于非单例的容器Bean,我们没有办法初始化的时候设置定义的属性类对象
	 * 需要在每次请求生成一个新的对象的时候重新进行依赖注入,不能在初始化的时候进行依赖注入
	 * @param beanInstance
	 * @throws Exception
	 * return_type:void
	 * creator:baiml
	 * create time:2020年5月19日
	 * modifier: 
	 * modify time:
	 */
	protected  void autoSetByPropto(Object beanInstance) throws Exception {
		if (beanInstance != null) {
			denpence(beanInstance);
		}

	}
	/**
	 * 
	 * method name:denpence
	 * description:Bean依赖注入
	 * @param beanInstance
	 * return_type:void
	 * creator:baiml
	 * create time:2020年5月19日
	 * modifier: 
	 * modify time:
	 * @throws Exception 
	 * @throws IllegalAccessException 
	 * @throws IllegalArgumentException 
	 */
	private void denpence(Object beanInstance) throws IllegalArgumentException, IllegalAccessException, Exception {
		String clname = beanInstance.getClass().getName();
		/**
		 * 如果beanInstance对象是包含切面的对象,那么就是Proxy代理的对象,而代理的对象一般都是接口
		 * 我们要依赖注入我们的对象,那么就需要得到真正代理的对象
		 */
		if(clname.startsWith("com.sun.proxy")) {
			ContainerProxy p = (ContainerProxy) Proxy.getInvocationHandler(beanInstance);
			beanInstance = p.getObject();
		}
		Field[] fields = beanInstance.getClass().getDeclaredFields();
		for (Field field : fields) {
			boolean isAccessable = field.isAccessible();
			field.setAccessible(true);
			if (field.isAnnotationPresent(AutoWired.class)) {
				// 实现了依赖注入的注解
				// 需要根据beanName查找对应的对象
				field.set(beanInstance, searchAutoWiredBean(field));
			}
			field.setAccessible(isAccessable);
		}
	
	}
	
	private  Object searchAutoWiredBean(Field field ) throws Exception {
		AutoWired auto = field.getAnnotation(AutoWired.class);
		String val = auto.value();
		String beanName = val;
		if(StringUtils.isEmpty(val)) {
			String fieldName = field.getName();
			beanName = fieldName.substring(0,1).toLowerCase() + fieldName.substring(1);
		}
		return getObject(beanFactory.get(beanName));
	}
	/**
	 * 
	 * method name:getObject
	 * description:通过容器获取类的对象
	 * @param fbean
	 * @return
	 * @throws Exception
	 * return_type:Object
	 * creator:baiml
	 * create time:2020年5月19日
	 * modifier: 
	 * modify time:
	 */
	private Object getObject(FactoryBean fbean) throws Exception {
		Object result = null;
		Object instance = fbean.getBeanInstance();
		if (instance != null) {
			result = instance;
		} else {
			Component component = fbean.getComponent();
			switch (component.beanType()) {
			case prototype:
				/**
				 * 如果是prototype,那么为每一个类定义了的服务重新生成一个对象
				 */
				Class<? extends Object> clzz = fbean.getBeanClzz();
				result = clzz.newInstance();
				break;
			case singleton:
				/**
				 * 单例,整个jvm中值存在一个对象,每一个类的field定义,容器中只能存在一个对象
				 */
				result = fbean.getBeanInstance();
				break;
			}
		}
		return result;
	}


	public void setAspectInfo() throws Exception {
		aspectInfo =  getAspectInfo();
	}

代码太多了,细节我就不说了,如果有兴趣的朋友又有没有明白的地方欢迎留言。
ApplicationContextFactory,主要通过它来获取Bean,负责从Bean工厂中取到Bean对象:

public class ApplicationContextFactory extends IOCFactory {

	private static ApplicationContextFactory applicationContextFactory;
	
	private ApplicationContextFactory() {}
	
	public static ApplicationContextFactory getApplicationContextFactoryInstance() {
		if(applicationContextFactory == null) {
			applicationContextFactory = new ApplicationContextFactory();
		}
		applicationContextFactory.containInit();
		return applicationContextFactory;
	}
	
	private void containInit() {
		try {
			init();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public  <T> T getBean(String beanName) throws Exception {
		T result =  null;
		FactoryBean fbean= beanFactory.get(beanName);
		if(fbean != null) {
			result = getBean(fbean);
		}
		return result;
	}
	public  <T> T getBean(Class<? extends T> clzz) throws Exception {
		String clzzSimpleName = clzz.getSimpleName();
		String beanName = clzzSimpleName.substring(0,1).toLowerCase() + clzzSimpleName.substring(1);
		return getBean(beanName);
	}
	
	@SuppressWarnings("unchecked")
	private <T> T getBean(FactoryBean fbean) throws Exception{
		T result = null;
		Object instance = fbean.getBeanInstance();
		if(instance != null) {
			result = (T) instance;
		}else {
			Component component = fbean.getComponent();
			Component.BEAN_TYPE bType = component.beanType();
			switch(bType) {
			case prototype:
				Class<? extends Object> clzz = fbean.getBeanClzz();
				result = (T) getInstanceByAspect(clzz);
				autoSetByPropto(result);
				break;
			case singleton:
				result = (T) instance;
				break;
			}
		}
		return result;
	}
}

AOP类的创建

AspectInfo,切面信息类:

public class AspectInfo {
	//切面对象的class
	private Class<? extends Object> aspectClzz;
	//代理的真实对象
	private Object trueProxy;
	//切点注解
	private Pointcut pointcut;
	//执行的调用的方法
	private Method beforeMethod;
	//执行成功过后调用的方法
	private Method afterMethod;
	//出现异常后的调用
	private Method afterTrxMethod;

	public Pointcut getPointcut() {
		return pointcut;
	}

	public void setPointcut(Pointcut pointcut) {
		this.pointcut = pointcut;
	}

	public Method getBeforeMethod() {
		return beforeMethod;
	}

	public void setBeforeMethod(Method beforeMethod) {
		this.beforeMethod = beforeMethod;
	}

	public Method getAfterMethod() {
		return afterMethod;
	}

	public void setAfterMethod(Method afterMethod) {
		this.afterMethod = afterMethod;
	}

	public Method getAfterTrxMethod() {
		return afterTrxMethod;
	}

	public void setAfterTrxMethod(Method afterTrxMethod) {
		this.afterTrxMethod = afterTrxMethod;
	}

	public Class<? extends Object> getAspectClzz() {
		return aspectClzz;
	}

	public void setAspectClzz(Class<? extends Object> aspectClzz) {
		this.aspectClzz = aspectClzz;
	}

	@Override
	public String toString() {
		return "AspectInfo [aspectClzz=" + aspectClzz + ", pointcut=" + pointcut + ", beforeMethod=" + beforeMethod
				+ ", afterMethod=" + afterMethod + ", afterTrxMethod=" + afterTrxMethod + "]";
	}

	public Object getTrueProxy() {
		return trueProxy;
	}

	public void setTrueProxy(Object trueProxy) {
		this.trueProxy = trueProxy;
	}
	
	
	

}

AspectFactory切面扫描类,也是继承了最上面的扫描父类:

public class AspectFactory {
	
	
	protected   List<AspectInfo> getAspectInfo() throws Exception {
		AbstractScanRegisterAnnon scan = new ScanAspectHandler();
		List<AspectInfo> aspectInfoList = null;
		List<Class<? extends Object>> list = scan.scanRegisterClass();
		
		if(list != null && list.size() > 0 ) {
			aspectInfoList = Lists.newCopyOnWriteArrayList();
			/**
			 * 1.找到poincut
			 */
			for(Class<? extends Object> clzz : list ) {
				AspectInfo aspectInfo = findMethods(clzz);
				aspectInfoList.add(aspectInfo);
			}
		}
		return aspectInfoList;
	}
	
	private AspectInfo findMethods(Class<? extends Object> clzz) throws Exception {
		Method methods [] = clzz.getDeclaredMethods();
		Pointcut pointcut = null;
		Method beforeMethod = null;
		Method afterMethod = null;
		Method afterExMethod = null;
		for(Method method : methods) {
			pointcut = findPointcut(method, pointcut);
			beforeMethod = findMethod(method, beforeMethod, BeforeRuning.class);
			afterMethod = findMethod(method, afterMethod, AfterReturning.class);
			afterExMethod = findMethod(method, afterExMethod, AfterThrowing.class);
		}
		AspectInfo aspectInfo = new AspectInfo();
		pointcutChk(aspectInfo, pointcut);
		aspectInfo.setAfterMethod(afterMethod);
		aspectInfo.setAfterTrxMethod(afterExMethod);
		aspectInfo.setBeforeMethod(beforeMethod);
		aspectInfo.setAspectClzz(clzz);
		return aspectInfo;
	}
	
	private void pointcutChk(AspectInfo aspectInfo,Pointcut pointcut ) throws Exception {
		if(pointcut == null) {
			throw new Exception("pointcut 未找到,请确认!");
		}
		if(StringUtils.isEmpty(pointcut.execution())) {
			throw new Exception("pointcut 未配置execution,请确认!");
		}
		aspectInfo.setPointcut(pointcut);
	}
	
	private Pointcut findPointcut(Method method,Pointcut pointcut) throws Exception {
		if(pointcut == null ) {
			if(method.isAnnotationPresent(Pointcut.class)) {
				pointcut = method.getAnnotation(Pointcut.class);
			}
		}
		return pointcut;
	}
	
	private Method findMethod(Method method,Method destMethod,Class<? extends Annotation> annotationClzz) throws Exception {
		if(destMethod == null ) {
			if(method.isAnnotationPresent(annotationClzz)) {
				destMethod = method;
			}
		}
		return destMethod;
	}
}

最后我们的容器代理,我这边用的JDK8的动态代理:
ContainerProxy:

public class ContainerProxy implements InvocationHandler {

   /**
    * 执行前调用的方法
    */
	private Method beforeMethod;
    /**
     * 正确执行成功调用的方法
     */
	private Method afterMethod;
    /**
     * 执行过程中出现异常的方法
     */
	private Method afterTrxMethod;
    /**
     * 切面对象
     */
	private Object aspectObject;
	/**
	 * 被代理的真实对象
	 */
	private Object object;

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Class<?>[] interfaces = proxy.getClass().getInterfaces();// 主调用的接口
		String methodName = method.getName();// 调用的方法名称
		Class<? extends Object> clzz = interfaces[0];
		System.out.println("ContainerProxy.invoke ----------调用接口:"+clzz.getName());
		System.out.println("ContainerProxy.invoke ----------调用方法:"+methodName);
		System.out.println("ContainerProxy.invoke ----------参数列表:"+args);
		System.out.println(proxy.getClass().getName());
		Object result = null;
		try {
			// 获取切入点的对象
			// 切入点开始调用
			if (beforeMethod != null) {
				beforeMethod.invoke(aspectObject, new Object[] { proxy, method, args });
			}
			result = method.invoke(object, args);
			if (afterMethod != null) {
				afterMethod.invoke(aspectObject, new Object[] { result });
			}
		} catch (Throwable ab) {
			ab.fillInStackTrace();
			if (afterTrxMethod != null) {
				afterTrxMethod.invoke(aspectObject, new Object[] { ab });
			}
			throw ab;
		}
		return result;
	}

	public void setBeforeMethod(Method beforeMethod) {
		this.beforeMethod = beforeMethod;
	}

	public void setAfterMethod(Method afterMethod) {
		this.afterMethod = afterMethod;
	}

	public void setAfterTrxMethod(Method afterTrxMethod) {
		this.afterTrxMethod = afterTrxMethod;
	}

	public void setAspectObject(Object aspectObject) {
		this.aspectObject = aspectObject;
	}

	public void setObject(Object object) {
		this.object = object;
	}

	public Object getObject() {
		return object;
	}

}

最后来编写测试类

我们上面已经定义完了我们的ioc和aop,那么我要验证我们是否正确:
首先编写一个接口TestService:

public interface TestService {
	
	String getMsg(String s);

}

再创建一个普通的class SysService类,也是注册成一个容器对象,里面提供了一个获取日期的方法:

@Component(beanType = BEAN_TYPE.prototype)
public class SysService {
	
	
	public String getSysdate() {
		
		return "20200519";
	}

}

component中的beanType不写,默认是单例,如果是prototype,那么每次请求时会重新创建一个新的对象或者代理对象。

我们创建一个普通的实体类,下一步我们把这个实体类注册成一个容器组件SysSerial:

public class SysSerial {
	
	private String txDate;
	private String cardNo;
	private BigDecimal txAmt;
	private Integer sn;
	public String getTxDate() {
		return txDate;
	}
	public void setTxDate(String txDate) {
		this.txDate = txDate;
	}
	public String getCardNo() {
		return cardNo;
	}
	public void setCardNo(String cardNo) {
		this.cardNo = cardNo;
	}
	public BigDecimal getTxAmt() {
		return txAmt;
	}
	public void setTxAmt(BigDecimal txAmt) {
		this.txAmt = txAmt;
	}
	public Integer getSn() {
		return sn;
	}
	public void setSn(Integer sn) {
		this.sn = sn;
	}
	@Override
	public String toString() {
		return "SysSerial [txDate=" + txDate + ", cardNo=" + cardNo + ", txAmt=" + txAmt + ", sn=" + sn + "]";
	}
	
	
	

}

然后我们在创建一个普通的类,这个类也注册到容器,这个类如果配置了@Bean,那么这个方法最后也会被容器扫描到并且将方法的返回对象作为一个Bean注册到容器:

@Component
public class SysConfiguration {

	/**
	 * 
	 * method name:sysSerial
	 * description:注册一个新的Bean
	 * @return
	 * return_type:SysSerial
	 * creator:baiml
	 * create time:2020年5月19日
	 * modifier: 
	 * modify time:
	 */
	@Bean(name = "sysSerial", propertys = { @Property(name = "txDate", value = "20200519"),
			@Property(name = "cardNo", value = "6231236547890000"), @Property(name = "txAmt", value = "98.50"),
			@Property(name = "sn", value = "100000001")})
	public SysSerial sysSerial() {

		System.out.println("我是新注册的Bean,启动初始化需要调用,我带了初始化参数");
		return new SysSerial();
	}
	@Bean(name = "abcdefg")
	public SysSerial sysSerial2() {
		System.out.println("我是新注册的Bean,启动初始化需要调用,我不带初始化参数");
		SysSerial serial = new SysSerial();
		serial.setCardNo("82323232323");
		serial.setSn(200001);
		return serial;
	}
	

}

我们再来创建一个切面类,这个切面定义一个规则,当然了,这个切面也是一个容器组件类:

@Aspect
@Component
public class TestAspect {
	
	@Pointcut(execution = "com.xxx.xxx.*.service.impl..*.*(..)")
	public void pointcut() {}
	
	@BeforeRuning
	public void beforeInvoke(Object proxy, Method method, Object[] args) {
		System.out.println("我是执行前的调用................");
	}
	
	@AfterReturning
	public void afterInvoke(Object ret) {
		System.out.println("我是执行成功后调用................ret=" + ret);
	}
	
	@AfterThrowing
	public void afterInvokeThr(Throwable ab) {
		System.out.println("我在在异常出现时调用................");
	}

}

以上的切面com.xxx.xxx..service.impl….*(…)中的xxx是公司和客户的包名,我这边隐藏;

以上的准备工作做好了,我们测试的第一步创建了一个接口,现在我们再创建一个实现类实现这个接口:

@Component(beanType = BEAN_TYPE.prototype)
public class TestServiceImpl implements TestService {

	@AutoWired
	private SysService SysService;
	
	@AutoWired
	private SysSerial sysSerial;
	
	@AutoWired(value = "abcdefg")
	private SysSerial sysSerial2;
	
	@Override
	public String getMsg(String s) {
		System.out.println(sysSerial);
		System.out.println(sysSerial2);
		return "cuuent date is "+SysService.getSysdate()+" @Component is ok!";
	}

}

上面都是通过@AutoWired进行注入的,也就是从容器中拿的对象,可以是单例,可以是多例;

最后我们编写一个测试类测试:

public class IOCTest {
	
	
	public static void main(String[] args) {
		ApplicationContextFactory acf = ApplicationContextFactory.getApplicationContextFactoryInstance();
		try {
			TestService service = acf.getBean(TestService.class);
			System.out.println(service.getMsg("ddd"));
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}

}

1.首先通过ApplicationContextFactory 拿到我们的Bean,得到bean可以根据class也可以根据beanName拿,根据自己的喜好来;
2.再者我们拿到我们想要的对象过后,进行调用,如果切面的pointcut是符合这个包访问路径了,就会调用切面的相对应的方法。
我们右键执行以下,出现结果如下:
在这里插入图片描述

结束语

我已经好多年不写博客了,今天突然有点时间,就想写以下博客,主要最近几年实在太忙了,家庭、工作、小孩实在是忙不开,所以可能水平有点不咋滴,请进入博客的各位看官包容,其实我就是单纯的想把一些自己的东西写到博客作为记录,可能有不对的地方,后面慢慢改进。最后2020年因为疫情的原因,让我们仿佛过了一个世界末日,最后望大家以后生活都安好。

最全面解析Spring框架IOC容器和AOP面向切面 一、Spring开源框架的简介 Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来。【参考文献】 它是为了解决企业应用开发的复杂性而创建的。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java 阅读详情

相关推荐

VMware 虚拟机里连不上网的五种解决方案

在VMware虚拟机里的虚拟机系统连接不上网络 首先,注意查看适配器选项里的网络连接这两个网络连接是否存在,如果不存在可以重新装一下VM 如果存在,连不上网 解决办法一: 虚拟机设置里,找到“网络适配器”,右边的网络连接选择“NAT 模式”,如果不行的话再linux系统。还是不行的话接着看第二种解决方案。 解决方法二: 可能原因是VMware NET Service...

墨轩 18万+

aop切面配置不起作用引发的spring容器和spring mvc容器关系学习

<aop:aspectj-autoproxy proxy-target-class="true"/>,为什么不起作用哪,原来是带有controller注解的类默认是 被spring mvc容器管理,而spring mvc的配置文件在spring-mvc.xml中

海角七号--kobe 1387

实例讲解Simulink应用层开发CAN报文解包及CAN信号设置方法

本文通过讲解MCU CAN解包模块的模块设置、输入输出信号的设置及仿真测试验证,说明了CAN解包模块的设置方法、CAN解包模块输入输出信号的设置方法以及CAN解包模块的仿真测试及修正方法。在模型搭建过程中,建议养成一种搭建完成仿真测试验证的习惯,在模块阶段发现错误,解决错误,避免在后期模块集成之后报出大量错误,增加解决错误的工作量和难度。希望通过本文的介绍能给相关技术人员带来一些参考和帮助。

qq_43011586的博客 5682

Spring AOP 切面(Aspect)应用详解

1. AOP 切面应用 下面是一个AOP切面的一个简单的应用实例 引入AOP依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> 创建切面类对象 @Aspect @Component public class ItemCach

weixin_44947701的博客 2776

雨流计数法的matlab实现,采用三点法与四点法

介绍雨流计数法是20世纪50年代由英国的两位工程师M.Matsuishi和T.Endo提出来的。该计数法的主要功能是把实测载荷历程简化为若干个载荷循环,供疲劳寿命估算和编制疲劳试验载荷谱使用。它以双参数法为基础,考虑了动强度(幅值)和静强度(均值)两个变量,符合疲劳载荷本身固有的特性。雨流计数法主要用于工程界,特别在疲劳寿命计算中运用非常广泛计数规则(1)雨流依次从载荷时间历程的峰值位置的内侧沿着...

u011391128的博客 3万+

LSTM cell结构的理解和计算

LSTM是传统RNN网络的扩展,其核心结构是其cell单元,网上LSTM的相关资料繁多,质量参差不齐,下面主要结合LSTM神经网络的详细推导和 Christopher Olah的blog两篇文章中的内容进行说明。主要介绍网络如何计算,为何这么算先不展开:)。前者一副图加上29个公式,简洁明了;后者娓娓道来,适合初学者。首先是LSTM cell最常见的结构图: 这是变形的版本(找不到更清晰的版本了),

songhk0209的博客 2万+

AOP(spring中)

Q为什么需要切面 A:事务模块不仅仅是为特定业务提供服务,还要处理系统辅组功能(日志记录,安全管理)。这时候我们就需要aop,将核心代码以及次要代码分隔开。这样做有两个好处:1.关注点代码都集中于一处,而不是分布在多代码,方便管理2.其次,服务模块更加简洁,因为他们只用关注功能逻辑的代码。以后需要添加辅助功能时候,也不会干涉到原本的类。 然后就会在运行期间,根据切入点动态织入目标对象中...

立志变成java巨头 427

【软考中级网络工程师】知识点之 ICMP 协议

本文聚焦软考中级网络工程师必备的 ICMP 协议知识,先概述其在 TCP/IP 协议族网络层的地位与无连接特性,再阐述差错报告、网络诊断等功能。解析报文格式,详解差错与查询类报文类型及工作机制,还介绍其在 Ping、Traceroute 命令中的应用,分析常见攻击与防范措施,最后总结核心要点,为网络工程师学习和应用 ICMP 协议提供全面指导。

邓邓子的博客 1405

ioc容器与aop(面向切面编程)的使用

一、ioc  1、准备jar包 &lt;dependency&gt; &lt;groupId&gt;org.springframework&lt;/groupId&gt; &lt;artifactId&gt;spring-context&lt;/artifactId&gt; &lt;version&gt;5.1.1.RELEASE&lt;/version&gt; &a

ZWY_Java的博客 298

基于深度学习的行人车辆检测与计数系统(UI界面+YOLOv8/v7/v6/v5代码+训练数据集)

从YOLOv1到最新的YOLOv8,其网络结构、训练策略和损失函数不断优化,性能持续提升。image_path, _ = QFileDialog.getOpenFileName(self, "选择图片文件", "", "Image Files (*.jpg *.png *.jpeg *.bmp)")video_path, _ = QFileDialog.getOpenFileName(self, "选择视频文件", "", "Video Files (*.mp4 *.avi *.mov *.mkv)")

YOLO 227

大模型的应用与微调:如何调用 LLM?从 OpenAI API 到本地部署

本篇文章介绍了如何调用 OpenAI、DeepSeek、Manus、通义千问等大模型 API,并探讨了 LLM 本地部署的方法。在实际应用中,可以根据需求选择云端 API 或本地化部署方案,以满足不同的计算需求和隐私要求。下一篇:大模型微调与 RAG 技术(LoRA、QLoRA、向量数据库)

晴天彩虹雨的博客 1157

Spring IOC系统总结+AOP面向切面编程+Spring事务

Spring IOC系统总结+AOP面向切面编程+Spring事务

weixin_53700782的博客 1483

TDS水质检测传感器原理图设计,已量产(液体传感器)

最近调试了一款针对生活用水、水培系统的 TDS 水质检测模块 —— 毕竟 TDS(总溶解固体)值直接关联水的洁净程度,是这类场景里既实用又易获取的水质指标。下面拆解下这个电路的设计逻辑,说说每个部分是怎么配合实现精准检测的。

不脱发的程序猿 1548

Spring的IOC和AOP原理

Spring的IOC和AOP原理 本文讲的是面试之Spring框架IOC和AOP的实现原理, IoC(Inversion of Control) (1). IoC(Inversion of Control)是指容器控制程序对象之间的关系,而不是传统实现中,由程序代码直接操控。控制权由应用代码中转到了外部容器,控制权的转移是所。 IoC(Inversion of Control) (1). IoC(Inversion of Control)是指容器控制程序对象之间的关系,而不是传统实现中,由程序代码直接操控。

子冉冰清的博客 2万+

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

Spring中的IOC和AOP是什么意思?

(1) Spring是什么? IOC(控制反转)和AOP(面向方面编程)作为Spring框架的两个核心,很好地实现了解耦合。所以,简单来说,Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。 spring的基本框架主要包含六大模块:DAO、ORM、AOP、JEE、WEB、CORE Spring DAO:Spring提供了对JDBC的操作支持:JdbcTemplate模板工具类 。 Spring ORM:Spring可以与ORM框架整合。例如Spring整...

weixin_45704311的博客 1万+

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

Spring IOC 和 AOP

Spring框架中的IoC(Inverse of Control,控制反转)和AOP(Aspect-Oriented Programming,面向切面编程)是其两大核心特性,它们共同为Java应用程序带来了更高的灵活性、可维护性和松耦合度。

Good good study,day day up 2859

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Spring实现IOC和AOP的底层原理

Spring框架是Java企业级应用开发中的核心框架之一,其核心思想可以概括为IOC(Inversion of Control,控制反转)和AOP(Aspect Oriented Programming,面向切面编程)。IOC通过依赖注入实现对象之间的解耦,而AOP则提供了一种在不修改源代码的情况下,为程序动态添加额外功能的技术手段。本文将深入探讨Spring实现IOC和AOP的底层原理。Spring的IOC和AOP是实现松耦合、高内聚和代码复用的重要手段。

qq_30009397的博客 2102

Spring 核心技术栈:IoC 容器 / AOP 切面 / 事务管理核心逻辑拆解

Spring 是 Java 企业级应用的核心开发框架,以控制反转(IoC)和面向切面编程(AOP)为核心基石。IoC 容器统一管理 Bean 的生命周期与依赖注入,彻底解耦对象间硬编码关联;AOP 将日志、事务等横切逻辑抽离为切面,实现与核心业务的无侵入融合。其声明式事务等特性大幅简化开发,且是 Spring Boot、Spring Cloud 等生态的基础,为 Java 应用提供高效、可扩展的开发解决方案。

计算机,知识点,实时记录 2067

Spring IOC(DI)+AOP

IOC容器其实就是一个Map,key是每个bean对象的ID,value是bean对象本身。IOC 容器负责创建bean对象并管理bean的生命周期。某个接口,就无法使用 JDK Proxy 去进行代理了,这时候 Spring AOP 会使用 Cglib,基于继承的方式,生成一个被代理对象的子类来作为代理(Cglib动态代理的核心是MethodInterceptor接口和Enhancer类);:指的是对象创建(实例化、管理)的权力。

2301_78423465的博客 1998

spring IOC和AOP的底层实现

spring IOC和AOP的底层实现 https://juejin.im/post/5bf51d4c5188256d9832b0d3 IOC 2、spring核心主要两部分: (1)aop:面向切面编程:扩展功能不是修改源代码实现 (2)Ioc:控制反转,比如有一个类,在类里面有方法(不是静态的方法,创建类的对象,使用对象调用方法,创建类对象的过程,需要new出来对象。 现在对象的创建不是通过n...

兰陵鸡王的博客 3770

Java 手写 Spring框架 IOC 和 AOP----手写Spring IoC和AOP

本文将首先通过手写Spring,了解Spring基本思想,然后介绍Spring的一些高级用法,随后深度剖析其源码,让读者有更深入的了解====本文源码基于5.1.12版本讲解

殷志鹏的博客 2541

Spring aop 和 ioc 介绍一下

1.ioc容器:实际上就是map(key,value),里面存放的是各种对象(在xml里面配置的bean节点、@repository,@service,@controller,@compent)在项目里启动的时候会读取配置文件里面的bean节点,创建对象到map里面。

qq_37163076的博客 1761

Java 模拟Spring,实现IOC和AOP的核心(一)

在这里我要实现的是Spring的IOC和AOP的核心,而且有关IOC的实现,注解+XML能混合使用! 参考资料: IOC:控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体,将其所依赖的对象的引用传递给它。也

“ 春风若有怜花意,能否许我再少年。” 1162

深入剖析Spring核心:IOC容器与AOP切面编程

理解 IOC 与 AOP,不仅能熟练使用 Spring 框架,更能掌握 “解耦” 的设计思想 —— 这也是 Java 高级开发的核心能力之一。后续可进一步深入学习 Bean 的作用域(如 singleton、prototype)、AOP 的切入点表达式优化、事务切面的实现细节等内容,夯实 Spring 技术栈基础。

Varin 832

深入理解Spring框架IOC容器和AOP

深入理解Spring框架IOC容器和AOPSpring开源框架的简介Spring下IOC容器和DISpring面向切面编程(AOP)概念定义: Spring开源框架的简介 Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。 Spring的基本框架主要模块:DAO、ORM、AOP、Context、WEB、CORE。 Spring DAO:Spring提供了对JDBC的...

李也的博客 2618

Spring的AOP和IOC

首先了解AOP呐就要了解spring的优点以及DI这个概念,来引入我们的AOP. spring 的优点? 1.降低了组件之间的耦合性 ,实现了软件各层之间的解耦 2.可以使用容易提供的众多服务,如事务管理,消息服务等 3.容器提供单例模式支持 4.容器提供了AOP技术,利用它很容易实现如权限拦截,运行期监控等功能 5.容器提供了众多的辅助类,能加快应用的开发 6.spring对于主流的应用框架提供...

wangziman的博客 2064
上一篇: DB2命令
下一篇: 利用Spring的@Import扩展点与spring进行无缝整合
Life  journey
博客等级 码龄17年 1万+粉丝 80原创
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值