1.Spring的IOC理解
1.1什么是IOC容器?
IOC即控制反转,把传统上由程序代码直接操控的对象转交给容器,通过容器来对组件进行装配和管理,即控制权由程序代码本身转交给了IOC容器来进行管理。
1.2IOC的作用
①管理对象的依赖创建和维护
②解耦,容器来管理和维护对象
③无需关心类的创建过程,直接使用
1.3IOC的优点
①IOC或依赖注入把应用的代码量降到最低
②容易进行测试
③将对象组件之间的耦合降到最低
④支持懒汉式和饿汉式选择创建
1.4IOC的实现机制
实现原理为工厂模式和代理模式
1.5IOC支持的功能
①依赖注入
②依赖检查
③自动装配
④支持集合
⑤指定初始化方法和销毁方法
⑥支持回调某些方法(但是需要实现 Spring 接口,略有侵入)
2.Spring的DI理解
2.1什么是Spring的依赖注入?
依赖注入更加准确的描述了IOC的设计理念,容器动态的将有依赖关系的对象注入到所需要它的对象中,让容器根据我们提供的依赖关系进行注入
2.2依赖注入的基本原则
容器全权负责组件的装配,它会把符合依赖关系的对象通过属性(JavaBean中的setter)或者是构造器传递给需要的对象
2.3依赖注入的实现方式
①使用属性的setter方法注入 ,这是最常用的方式;
②使用构造器注入;
③使用Filed注入(用于注解方式)
2.3.1setter方法注入
public class Car {
private String brand;
public String getBrand() {
return brand;
}
//一定要写被注入对象的set方法
public void setBrand(String brand) {
this.brand = brand;
}
public void run(){
System.out.println("brand:"+brand+",maxSpeed:"+maxSpeed+",price:"+price);
}
}
<!-- 属性注入 -->
<bean id="car" class="com.spring.model.Car">
<property name="brand" value="红旗CA72"></property>
</bean>
public void test(){
//读取配置文件
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
//获取bean的实例
Car car=(Car) ctx.getBean("car");
car.run();
}
2.3.2构造器注入
public class Car {
private String brand;
//带参构造方法
public Car(String brand){
this.brand=brand;
}
public void run(){
System.out.println("brand:"+brand+",maxSpeed:"+maxSpeed+",price:"+price);
}
}
①按类型匹配入参
<!-- 构造函数注入(按类型匹配) -->
<bean id="car1" class="com.spring.model.Car">
<constructor-arg type="java.lang.String" value="宝马"></constructor-arg>
</bean>
①按索引匹配入参
<!-- 构造函数注入(按索引匹配) -->
<bean id="car2" class="com.spring.model.Car">
<!-- 注意索引从0开始 -->
<constructor-arg index="0" value="中国一汽"></constructor-arg>
</bean>
2.3.3.使用字段(Filed)注入(用于注解方式)
不使用注解注入
<bean id="commonDao" class="com.spring.dao.impl.CommonDaoImpl"></bean>
<bean id="commonService" class="com.spring.service.impl.CommonServiceImpl">
<!-- 注入持久化访问所需的DAO组件 -->
<property name="commonDao" ref="commonDao"/>
</bean>
byName:通过bean的名称进行自动装配,如果一个bean的 property 与另一bean 的name 相同,就进行自动装配。
byType:通过参数的数据类型进行自动装配。
在commonDao和commonService也要加上@Repository和@Service注解,xml中添加扫描(此处省略)
@Resource(name = "accountDao1") //默认是按照名称来装配注入的,找不到名称按类型注入
private AccountDao accountDao;
@Autowired //默认是按照类型装配注入的
private AccountDao accountDao;
@Autowired //默认是按照类型装配注入的
@Qualifier("accountDao1") //指定应该装配哪个确切的 bean 来消除歧义
private AccountDao accountDao;
3.Spring的AOP理解
3.1什么是AOP
①aop是面向切面编程,不同于原始的oop是面向对象编程,使用aop可以实现不需要修改源代码,只用修改一些配置便可以实现功能的拓展
②减少了代码量
③运行期间通过代理的方式向目标类植入代码
④运用场景有事务管理,缓存,性能监控,日志和安全检查等
3.2AOP的动态代理有哪些
JDK动态代理要比cglib代理执行速度快,但性能不如cglib好。所以在选择用哪种代理还是要看具体情况,一般单例模式用cglib比较好
①JDK动态代理
/**
* CGLIB代理
*/
public class CGLIBProxy implements MethodInterceptor {
public Object targetObject;
public Object createProxyInstance(Object targetObject){
this.targetObject=targetObject;
Enhancer enhancer = new Enhancer();
//设置代理目标
enhancer.setSuperclass(targetObject.getClass());
//设置回调
enhancer.setCallback(this);
return enhancer.create();
}
/**
* 在代理实例上处理方法调用并返回结果
* @param object : 代理类
* @param method :被代理的方法
* @param args :该方法的参数数组
* @param methodProxy
*/
@Override
public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object result = null;
try {
System.out.println("前置处理开始 ...");
result = methodProxy.invoke( targetObject , args);//执行目标对象的方法
System.out.println("后置处理开始 ...");
} catch (Exception e) {
System.out.println("异常处理 ...");
} finally {
System.out.println("调用结束 ...");
}
return result;
}
}
②cglib代理
/**
* 动态代理
*/
public class Creatproxy implements InvocationHandler {
//创建被代理的对象
private Object target;
//创建代理对象的方法
public Object creatprexy(Object target){
this.target=target;
//target.getClass().getInterfaces()得到被代理对象的接口,当前创建代理对象类Creatproxy的对象
Object proxy= Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces() ,this );
return proxy;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("想要找一份高薪的程序员工作");
method.invoke(target,args);
System.out.println("成功录取,从此走上人生巅峰");
return null;
}
}