Spring,Spring Boot,IOC,AOP,实例化属性注入
1、Spring、Spring Boot / IOC
1. IOC Inversion of Control 控制反转
控制反转是一种思想,在java中对对象实例的创建、管理的思维方式。
类实例化方式有:传统模式(new),以及使用反射技术实现。
Class<?> aClass = Class.forName(clazz);
Object o = aClass.newInstance(); // 实例化之后的对象
传统创建对象实例使用方式,在依赖类中new出实例对象使用,而IOC模式,不需要自己创建实例,由IOC帮助实例化对象,并集中在IOC容器中进行管理。
2. 如何理解IOC 控制反转?
控制:即类实例化以及管理的权力
反转:控制权交给外部环境(Spring框架,IOC容器)
即传统模式对象实例化的主动权在于编码时的需要,引入IOC概念以后,这个实例化的主动权在于IOC容器。
IOC控制反转,一定程度上减少了代码的耦合,不再需要经常实例化对象,需要时即引用。
3. DI Dependency Injection 依赖注入
DI (依赖注入)与IOC描述的是同一件事情,描述的角度不一样。
IOC是从对象的角度:即对象的实例化、管理权力交给框架
DI是从IOC容器角度:即容器主动把类依赖的对象,主动将实例化对象送给对象类。
IOC主动获取,DI主动推送
2、Spring AOP
1. AOP Aspect Oriented Programming 面向切面编程
AOP是OOP的延续,(OOP 面向对象编程)是一种垂直纵向的继承体系,垂直开发。
AOP横切,切面编程,横向提取机制,横切逻辑代码在不变业务逻辑的情况下,横向切取重复点,提取重复解耦合。
自定义注解实现Spring AOP 切面编程(动态代理)示例:https://blog.csdn.net/loney_wolf/article/details/115299576
3、Spring Bean.xml配置,与Spring Boot注解注册实例
1. Spring Bean.xml配置实例对象
类实例化的两种方式:传统方式(new)、通过反射实例化
// 通过反射技术实例化对象,首先加载对象类
Class<?> aClass = Class.forName(clazz);
Object o = aClass.newInstance(); // 实例化之后的对象
Spring获取到xml中配置的类对象路径后,通过反射技术实例化对象(Spring 反射实现源码后续贴出),Spring Bean.xml配置:
<beans>
<!--id标识对象,class是类的全限定类名-->
<bean id="accountDao" class="com.xxx.JdbcTemplateDaoImpl">
<!-- name:参数名 ref:依赖引用类id -->
<property name="ConnectionUtils" ref="connectionUtils"/>
<!-- name:参数名 value:入参值 -->
<property name="xxx" value="xxx"/>
</bean>
<beans>
Spring对象中一个借口类有多个实现类时,在依赖的时候可通过配置不同的property参数实现引用。
2. Spring boot接口有多个实现类的时注入方式
//实例化注册
@service(name = "profileName")
//依赖注入
@Qualifer(name = "profileName")
@AutoWird
4、如何实现实例对象属性注入
示例:简单实现Parent类中注入Son类,通过实例对象属性注入调用Son类中的method
public class Parent {
private Son son;
void bb() {
System.out.println("我是父类对象");
son.aa();
}
}
public class Son {
void aa() {
System.out.println("我是子类对象");
}
}
public class InjectionTest {
@Test
public void testInjection() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
//第一步实例化两个对象,两种实例化对象方式,随便用
//将文件反射加载为Class对象
Class sonClazz = Class.forName("com.huey.Son");
Class parentClazz = Class.forName("com.huey.Parent");
Object sonBean = sonClazz.newInstance();
Object ParentBean = parentClazz.newInstance();
//获取到实例对象后,进行属性注入
//第一步获取到被注入类中声明对象
Field field = parentClazz.getDeclaredField("son");
//第二步开启属性的强行读写
field.setAccessible(true);
//第三步注入属性
field.set(ParentBean, sonBean);
//第四步,注入完成后进行测试
Parent parentClass = (Parent) ParentBean;
parentClass.bb();
}
}
/**
测试结果:
Connected to the target VM, address: '127.0.0.1:50570', transport: 'socket'
我是父类对象
我是子类对象
Disconnected from the target VM, address: '127.0.0.1:50570', transport: 'socket'
Process finished with exit code 0
由输出结果可见,实现属性注入以后,Parent类中声明的Son对象是成功注入,并且调用到了Son类中定义的输出方法。
*/