Spring IOC
Bean的作用域与生命周期
singleton作用域
lazy-init是懒加载, 如果等于true时作⽤是指Spring容器启动的时候不会去实例化这个bean, ⽽是 在程序调⽤时才去实例化. 默认是false即Spring容器启动时实例化
lazy-init属性(懒加载)
如果为false,则在IOC容器启动时会实例化bean对象,默认false
如果为true,则IOC容器启动时不会实例化Bean对象,在使⽤bean对象时才会实例化
lazy-init设置为false有什么好处?
1)可以提前发现潜在的配置问题
2)Bean 对象存在于缓存中,使⽤时不⽤再去实例化bean,加快程序运⾏效率
什么对象适合作为单例对象?
⼀般来说对于⽆状态或状态不可改变的对象适合使⽤单例模式。(不存在会改变对象状态的成员变 量) ⽐如:controller层、service层、dao层 } }
什么是⽆状态或状态不可改变的对象?
实际上对象状态的变化往往均是由于属性值得变化⽽引起的,⽐如user类 姓名属性会有变化,属性姓 名的变化⼀般会引起user对象状态的变化。对于我们的程序来说,⽆状态对象没有实例变量的存在,保 证了线程的安全性,service 层业务对象即是⽆状态对象。线程安全的。
prototype作用域
通过scope=“prototype” 设置bean的类型 ,每次向Spring容器请求获取Bean都返回⼀个全新的Bean,相 对于"singleton"来说就是不缓存Bean,每次都是⼀个根据Bean定义创建的全新Bean。
bean的定义
在Spring中,通常是通过配置⽂档的⽅式来定义Bean的。
在⼀个配置⽂档中,可以定义多个Bean。
bean的初始化
①::在配置⽂档中通过指定 init-method 属性来完成。
<!-- 通过init-method属性指定⽅法 -->
<bean id="roleService" class="com.xxxx.service.RoleService" init-method="init"></bean>
②:实现 org.springframework.beans.factory.InitializingBean 接⼝
public class RoleService implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("RoleService init...");
}
}
Bean对象实例化过程是在Spring容器初始化时被实例化的,但也不是不可改变的,可以通过 lazyinit=“true” 属性延迟bean对象的初始化操作,此时再调⽤getBean ⽅法时才会进⾏bean的初始化操作
Bean的使用
①:使⽤ BeanFactory
②:使⽤ ApplicationContext
Bean的销毁
实现销毁⽅式(Spring容器会维护bean对象的管理,可以指定bean对象的销毁所要执⾏的⽅法)。
①:实现销毁⽅式(Spring容器会维护bean对象的管理,可以指定bean对象的销毁所要执⾏的⽅ 法)
<bean id="roleService" class="com.xxxx.service.RoleService" destroy-method="destroy">
</bean>
②:通过 AbstractApplicationContext 对象,调⽤其close⽅法实现bean的销毁过程
AbstractApplicationContext ctx=new ClassPathXmlApplicationContext("spring.xml");
ctx.close();
Spring AOP
1.代理模式
代理模式是Java开发中一种比较常见的设计模式。设计目的在服务类和客户类之间插入其他功能,插入的功能对于调用者是透明的,起到了伪装控制的作用。
1.1代理类和委托类有相类似的行为
1.2代理类增强委托类的行为
2.静态代理
为某一个对象提供一个代理,代理角色固定,以控制对这个对象的访问。
代理类和委托类有共同的父类或者父接口,这样在任何委托类对象的地方都可以用代理对象替代。
代理类负责请求的预处理,过滤,将请求分派给委托类处理,以及委托类的执行完请求后的后续处理
2.1代理三要素
①:有共同的行为----接口
②:目标角色----实现行为
③:代理角色----实现行为----增强目标角色
2.2静态代理特点
①:目标角色固定
②:在应用程序执行前就得到目标角色
③:代理对象会增强目标的行为
④:有可能存在多个代理,引起"类爆炸"(缺点)
3.动态代理
3.1特点:
①:目标对象不固定
②:在应用程序执行时动态创建目标对象
③:代理对象会增强目标对象的行为
3.2JDK动态代理
注:JDK动态代理的目标对象必须有接口实现
实现InvocctionHandler接口
重写接口中仅有的一个invokee(Object proxy, Method method, Object[] args) 方法
proxy 调用方法的代理实例 method被代理的方法, 目标方法的形参
Proxy类下面的静态方法
newProxyInstance (ClassLoaderloader, Class[] interfaces)方法
返回一个代理类
3.3CGLIB动态代理
cglib 是针对类来实现代理的,它的原理是对指定的⽬标类⽣成⼀个⼦类,并覆盖其中⽅法实现增强,但因为 采⽤的是继承,所以不能对final修饰的类进⾏代理。
pom中添加依赖
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
实现MethodInterceptor接口
重写其中仅有的一个intercept()方法
3.4JDK代理与CGLIB代理的区别
JDK动态代理实现接口,Cglib动态代理继承父类
JDK动态代理(目标对象存在接口时)执行效率高于Ciglib
如果目标对象有接口实现,选择JDK代理,如果没有选择Cglib代理
4.Spring AOP
Aspect Oriented Programing ⾯向切⾯编程
4.1AOP能做什么
AOP主要应用于日志记录,性能统计,安全控制,事务处理等方面,实现公共功能性的重复使用
4.2AOP的特点
①:降低了模块和模块直接的耦合度,提高了业务代码的聚合度
②:提高了代码的复用性
③:提高了系统的扩展性
④:可以在不影响原有功能的基础上添加新功能
4.3AOP底层实现
动态代理(JDK+CGLIB)
4.4Join point连接点
被拦截到的每一个点,spring中值被拦截到的每一个方法,spring aop一个连接点即代表一个方法的执行
4.5point cut切点
对连接点进行拦截的定义(匹配规则定义 规定拦截哪些方法,对哪些方法进行处理),spring有专门的表达式语言定义。
4.6Advice(通知)
拦截到每一个连接点,即每一个方法后所要做的操作
①:前置通知(前置增强)–before()执行方法前通知
②:返回通知(返回增强)–afterReturn方法正常结束后返回通知
③:异常抛出通知(异常抛出增强)–afterThrow()
④:最终通知–after 无论是否发生异常,均会执行该通知
⑤:环绕通知–around 包围每一个连接点(jion point)的通知,如方法调用。
这是最强大的一种通知类型,环绕通知可以在方法调用前后完成自定义行为。它也会选择是否继续执行连接点或直接返回他们自己的返回值或者抛出异常来结束执行。
4.7Aspect(切面)
切入点与通知的结合,决定了切面的定义,切入点的定义了要拦截哪些类的哪些方法,通知则定义了拦截方法后要做什么,切面则是横切的关注点的抽象,与类相似,类是物体特征的抽象,切面是横切关注点的抽象。
48.Target(目标对象)
被代理的目标对象
4.8Weave(织入)
将切面应用到目标对象并生成代理对象的过程即为织入
4.9Introduction(引入)
在不修改原有应用程序代码情况下,在程序运行期为类动态添加方法或者字段的过程称为引入