- IOC
- 控制反转和依赖注入
- 为什么要使用依赖注入
- IOC的使用
- 自动配置
- java配置
- xml配置
- 混合配置
- Spring对bean生命周期的管理
- AOP
- 什么是AOP、AOP的好处
- 代理技术
- 动态代理
- JDK动态代理
- CGLIB动态代理
- AOP术语
- AOP的使用
- 注解配置
控制反转即组件的调用方不参入组件的创建配置和管理.而是将这些任务交给第三方去做即IOC容器。使得获取依赖组件的方式由自身获取(new对象)变成为IOC容器的主动注入。
依赖注入是Spring的一种编程方式,当组件A依赖于组件B时,我们就可以把组件B设置成A的成员变量来用IOC容器主动注入。
两者在本质上是一样的。
主要原因: 通过new的方式为成员变量进行赋值,这时主业务与依赖的组件类深度绑定(属于强耦合),这样的代码对于更新来说非常困难(这样对主业务进行修改不符合开闭原则)。使用依赖注入的思想可以解耦合,使得程序变得容易维护。
IOC的使用 自动配置Spring的自动装配是基于"组件扫描"和"自动装配"这两大技术。组件扫描来查找@Component注解,对发现的java类进行装配。通过@Autowired注解进行自动装配。
自动配置这种方式是配置javaBean的首选
@Configuration //该标签说明该类是一个java配置类
@ComponentScan //开启了自动扫描,可以指定需要扫描的包名。如果没有指定包名,则会扫描该配置类所在的包以及子包
public class Config {
}
//该注解会将该类标记为IOC容器中的一个bean,当扫描到该类时,会将其添加到IOC容器中去
@Component
public class Student {
private Person person;
public Student(){}
//自动装配注解
@Autowired
public Student(Person person){
this.person = person;
}
}
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@documented
public @interface Autowired {
// 当没有合适的类型注入时,默认true会报错,当设置为false时,将不会报错,而是直接赋值为null。
boolean required() default true;
}
当出现冲突时,可以使用@Qualifier注解进行解决。
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@documented
public @interface Qualifier {
String value() default ""; //设置限定符
}
java配置
当不能在源码上添加注解时,就不能进行自动配置了。这时我们就应该使用基于java的配置方式。
@Configuration //该注解标记该类是一个基于java的配置类
@ComponentScan
public class Config {
@Bean("BeanName")
public Person getPerson(){ //若该方法里面有参数,方法的调用方Spring框架会进行自动装配.出现冲突可在值的前面加上注解@Qualifier进行解决
return new Person();
}
}
需要注意的是当该配置类的其他方法调用@Bean注解的方法来满足自身依赖时,默认情况下该方法会被拦截并且不会执行该方法而是直接返回一个当初创建的bean(默认情况下bean是单例的)
xml配置混合配置
在javaConfig中引入javaConfig用@import(javaConfigName.class)
在javaConfig中引入xml用@importResource("xmlName.xml")
在xml中引入xml配置文件用
CGLIB动态代理
public Object cglibProxy(Object obj){
Enhancer enhancer = new Enhancer();
enhancer.setClassLoader(CglibProxy.class.getClassLoader());
enhancer.setSuperclass(obj.getClass());
MethodInterceptor interceptor = new MethodInterceptor(){
@Override
public Object intercept(Object o, Method method, Object[] objects,
MethodProxy methodProxy) throws Throwable {
System.out.println("---cglib log---");
Object ret = method.invoke(obj, objects);
return ret;
}
};
enhancer.setCallback(interceptor);
Object proxy = enhancer.create();
return proxy;
}
AOP术语
通知:通知定义了切面要完成的任务以及何时执行该任务(什么和何时)。
连接点:程序执行过程中能够插入切面的点。这些点可以是调用方法时、抛出异常时甚至是修改字段时(何处)。
切点:切点就是实际上需要插入切面的连接点,切点的定义有助于缩小连接点的范围。
切面:通知加切点构成了切面。
织入:织入就是把切面应用到目标对象上创建代理对象的过程。
AOP的使用
注解配置
配置一个切面类
@Aspect //该注解表明该类是一个切面类。
public class Audience {
@Before("execution(* SpringAOP.Perform.* (..))")
public void before(){
System.out.println("前置方法执行了");
}
}
注解 通知 @After 通知方法会在目标方法返回或抛出异常时调用 @AfterReturning 通知方法会在目标方法返回后调用 @AfterThrowing 通知方法会在目标方法抛出异常时调用 @Around 通知方法会将目标方法封装起来 @Before 通知方法会在目标方法调用前执行
基于java的配置类
@Configuration
@ComponentScan
@EnableAspectJAutoProxy //启用自动代理,如果没有开启自动代理,Audience类只会被当成一个普通的POJO
public class Config {
@Bean
public Audience audience(){
return new Audience();
}
@Bean
public Perform perform(){
return new Perform();
}
这时从IOC容器中获取的Perfrom对象就不是本来的Perform对象了,而是Perform对象的代理对象。



