一、Spring是什么?
Spring框架,是一个非常强大的反转控制(IOC)和面向切面编程(AOP)框架,以帮助分离项目组件之间的依赖关系。
Spring AOP与IOC
1. IoC(Inversion of control): 控制反转
概念:控制权由对象本身转向容器;由容器根据配置文件去创建实例并创建各个实例之间的依赖关系
核心:bean工厂;在Spring中,bean工厂创建的各个实例称作bean
2. AOP(Aspect-Oriented Programming): 面向方面编程
代理的两种方式:
静态代理:
针对每个具体类分别编写代理类;
针对一个接口编写一个代理类;
动态代理:
针对一个方面编写一个InvocationHandler,然后借用JDK反射包中的Proxy类为各种接口动态生成相应的代理类。
Spring的核心是IOC
IOC是什么? 对于Spring来说 ico就是spring控制对象的生命周期和对象之间的关系,也就是说之前需要用一个类的对象的时候需要我们手动去new Object()而现在将这个过程交给spring处理 将所有的类在spring中登记 需要的时候将他提供出去就可以了。假如我们需要操作数据库,以前我们的方法是创建一个dao接口的对象 并且对她进行实例化,这样提高了类与类之间的耦合度,现在我们只需要在spring中注册这个dao类 然后在service中需要依赖dao才可以实现一些功能,这个时候spring就将dao注入到service这个节点中,就实现了依赖注入,(设值注入和构造注入均可,但是一般采用设值注入)
二、动态代理
不用写代理类,虚拟机根据真实对象实现的接口产生一个类,通过类实例化一个动态代理,在实例化动态代理时将真实对象及装备注入到动态代理中,向客户端公开的是动态代理,当客户端调用动态代理方法时,动态代理根据类的反射得到真实对象的Method,调用装备的invoke方法,将动态代理、 Method、方法参数传与装备的invoke方法,invoke方法在唤起method方法前或后做一些处理。
1、产生动态代理的类:
java.lang.refect.Proxy
2、装备必须实现
InvocationHandler接口实现invoke方法
三、类的反射
什么是类的反射
类的反射就是通过类的说明能够得到这个类的父类、实现的接口、内部类、构造方法、方法、属性,并可以根据构造器获得该类的一个实例,唤起一个方法,取属性值,改属性值。如何得到一个类的说明?
Class cls = 类.class;
Class cls = 对象.getClass();
Class cls = Class.forName(“类路径”);
如何得到一个方法并唤醒他?
Class cls=类.class;
Constructor cons=cls.getConstructor(new Class[]{String.class});
Object obj=cons.newInstance(new Object[]{“aaa”});
Method method=cls.getMethod(“方法名”,new Class[]{String.class,Integer.class});
method.invoke(obj,new Object[]{“aa”,new Integer(1)});
四、Spring的注入方式
spring的注入方式有三种:
设值注入(setter)
构造注入(constructor)
接口注入(interface)
1.setter设值注入
//UserServiceImpl.java
package com.dlf.service.impl;
public class UserServiceImpl implements IUserService{
@Resource
private IUserDao dao; //具体实例化的过程会交给Spring处理
public void setDao(IUserDao dao) {
this.dao = dao;
}
@Override
public List<UserModel> query() {
return dao.query();
}
}
//applicationContext.xml
//注册UserDaoImpl类
<bean id="userDaoImpl" class="com.dlf.dao.impl.UserDaoImpl"></bean>
//注册UserServiceImpl类并且通过设值注入给UserServiceImpl实例化userDaoImpl对象
<bean id="userServiceImpl" class="com.dlf.service.impl.UserServiceImpl">
//这个name属性值要与UserServiceImpl类中需要实例化对象的属性值的名称相同
<property name="dao" ref="userDaoImpl"></property>
</bean>
这样过后UserServiceImpl中的dao对象就可以使用啦。
2.constructor构造注入
//UserServiceImpl.java
package com.dlf.service.impl;
public class UserServiceImpl implements IUserService{
@Resource
private IUserDao dao;
//在这里需要添加一个需要使用的参数的构造方法
public UserServiceImpl(IUserDao dao) {
super();
this.dao = dao;
}
@Override
public List<UserModel> query() {
return dao.query();
}
}
//applicationContext.xml
//注册UserDaoImpl类
<bean id="userDaoImpl" class="com.dlf.dao.impl.UserDaoImpl"></bean>
//注册UserServiceImpl类并且通过构造注入给UserServiceImpl实例化
<bean id="userServiceImpl" class="com.dlf.service.impl.UserServiceImpl">
<constructor-arg>
<ref bean="userDaoImpl"/> //这里使用了注册类中的UserDaoImpl资源,来进行dao的实例化
</constructor-arg>
</bean>
以上是构造方法中的参数为一个类的对象的时候,下面将介绍构造方法为一个或两个基本类型的数据的时候该怎么写
<bean id="userAction" class="com.dlf.action.User">
<constructor-arg value="admin"></constructor-arg> //构造方法只有一个String类型的参数
</bean>
<bean id="userAction" class="com.dlf.action.User">
<constructor-arg value="admin"></constructor-arg> //这里的构造方法只有一个String类型的参数
</bean>
<bean id="userAction" class="com.dlf.action.User">
<constructor-arg value="admin" index="0"></constructor-arg> //一个String类型的参数
<constructor-arg value="23" type="int" index="1"></constructor-arg> //还有一个整型的参数
</bean>
四、Spring的注解
为了减少xml文件中代码的数量,spring提供了注解方式来代替类的注册,提高了开发效率。
首先要让框架知道你要给哪些类添加注解
xmlns:context="http://www.springframework.org/schema/context"
<context:component-scan base-package="com.dlf"></context:component-scan> //在这里给com.dlf包中的所有java类添加注解
//UserAction.java
package com.dlf.action;
@Component //这里是给这个类添加注解
public class UserAction extends ActionSupport{
@Resource //注解类中需要的属性
private IUserService service;
private List<UserModel> list;
public List<UserModel> getList() {
return list;
}
public void setList(List<UserModel> list) {
this.list = list;
}
public String query(){
list = service.query();
return this.SUCCESS;
}
}
相当于
<bean id="userAction" class="com.dlf.action.UserAction">
<property name="service" ref="userServiceImpl">
</bean>
五、Spring的AOP
AOP(Aspect-OrientedProgramming)面向方面编程,与OOP完全不同,使用AOP编程系统被分为方面或关注点,而不是OOP中的对象。
主要功能
日志记录,性能统计,安全控制,事务处理,异常处理等等。
主要意图
将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。
1、首先先将applicationContext.xml中的Namespaces里面的aop和tx勾选上
2、
<!-- 日志配置 -->
<aop:config>
<!-- 配置切面类 -->
<aop:aspect ref="logUtil">
<!-- 设置切入点 execution(* com.zb.service.*.*(..)) 代表com.zb.service包下的所有的类中的所有的方法都会被切面类截断-->
<aop:pointcut expression="execution(* com.dlf.service.*.*(..))" id="logPointCut"/>
<!-- 配置什么时候进行拦截 -->
<aop:before method="beforeMethod" pointcut-ref="logPointCut"/>
<aop:after method="afterMethod" pointcut-ref="logPointCut"/>
</aop:aspect>
</aop:config>
<!-- 配置AOP事务 -->
<aop:config>
<!-- 配置切入点 -->
<aop:pointcut expression="execution(* com.dlf.service.*.*(..))" id="txPointCut"/>
<!-- 配置连接点 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>
<!-- 引入切面类 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<constructor-arg>
<ref bean="dataSourceDBCP"/>
</constructor-arg>
</bean>
<!-- 配置连接点 -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<!-- 设置事务的传播属性 -->
<tx:attributes>
<tx:method name="add*" propagation="REQUIRED"/>
<tx:method name="save*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="insert*" propagation="REQUIRED"/>
<tx:method name="delete*" propagation="REQUIRED"/>
<tx:method name="remove*" propagation="REQUIRED"/>
<tx:method name="query*" propagation="NOT_SUPPORTED"/>
<tx:method name="get*" propagation="NOT_SUPPORTED"/>
<!-- 命名不规范的时候默认选择 REQUIRED-->
<tx:method name="*"/>
</tx:attributes>
</tx:advice>