Open-source framework, starts from 2003, light-weight, full-stack.
AOP: 面向切面,扩展功能不是修改源代码实现。
IOC (控制反转), 比如有一个类,在类里面有方法(不是静态方法),调用类里面的方法,使用对象调用方法,创建类对象过程,需要new出来对象 把对象的创间不是通过new方法实现,而是交给spring配置创建类对象。
- spring, provides all layers solutions.
Web layer: springMVC
service layer: IoC of Spring
dao layer: jdbcTemplate of Spring
*ioc的配置文件
*ioc的注解方式
使用技术:1. xml配置文件; 2. dom4j解析xml; 3. 工厂的设计模式; 4. 反射技术
Code 原理
publicclassUser{
publicvoidadd() {
.....
}
}
// Call method - old way /* 在servlet中调用User类里面的内容,如果类名和方法发生改变,需要改变的东西太多。 耦合度太高了。*/Useruser = newUser();
user.add();publicclassUserService {
publicvoidadd() {
}
}
publicclassUserServlet{
UserServiceuserService = UserFactory.getService();
userService.add();
}
// Solution: create factory class. publicclassUserFactory{
// provide one method returns UserService object. publicstaticUserServicegetService() {
returnnewUserService();
}
}思想: 高内聚,低耦合
publicclassUserService{
}
publicclassUserServlet {
// get object UserServiceUserFactory.getService();
}
/** Step 1. Create xml file, configure to class you want to create. <bean id="userService" class="com.liyiandxuegang.package.UserService" /> Step 2. Create one Factory class, use dom4j to parse configuration file + reflection tech. public class UserFactory{ // return UserService public static UserService getService() { // 1. Use dom4j parse xml file. // According to id value, get the class property value responding to the id. String classValue = "from xml class property value"; // 2. Use reflection create object Class clazz = Class.forName(classValue); // 3. Use reflection create object UserService userService = clazz.newInstance(); return userService; } } */Step 1. Import jar files
(1) Release.jar, javadoc.jar, sources.jar
(2) Basic jars: Beans, Core, Context, SpEL (Core container)
(3) Import logging.jar
Step 2. Create class and method inside of class.
Step 3. create spring xml file, configure the class
Spring core configuration name and location is not fixed. But better under /src.
引入约束 schema
Configure the class
Step 4. Create test.
@TestpublicvoidtestUser() {
//1. load configuration fileApplicationContextapplicationContext = newClassPathXmlApplicationContext("bean1.xml");
//2. Get objectUseruser = (User) applicationContext.getBean("user");
//3. Testuser.add();
}- Bean 实例化方式
在spring里面通过配置文件创建对象
bean实例化三种方式:
使用类的无参构造函数
使用静态工厂创建
在类中创建静态方法,返回类对象
<beanid="bean2"class="com.liyiandxuegang.bean.Bean2Factory"factory-method="getBean2" /> publicclassBean2 { publicvoidadd() { System.out.println("Bean 2 ------ Add"); } } publicclassBean2Factory { // static methodpublicstaticBean2getBean2() { returnnewBean2(); } } @TestpublicvoidtestStaticFactory() { // load ApplicationContextapplicationContext = newClassPathXmlApplicationContext("bean1.xml"); Bean2bean2 = (Bean2) applicationContext.getBean("bean2"); bean2.add(); }
使用实例工厂创建()
创建一个不是静态的方法,,返回类的对象
<!-- Createfactoryobject --> <beanid="bean3Factory"class="com.liyiandxuegang.bean.Bean3Factory" /> <beanid="bean3"factory-bean="bean3Factory"factory-method="getBean3" />
id (name can be anything)
class: class qualified path
name: same as id, but id can't have special chars.
scope: singleton(default), prototype, request, session, globalSession: (ssl)
- 有参构造函数
publicclassUser{ privateStringname; publicUser(Stringname) { this.name = name; } } Useruser = newUser("abcde");
- 使用set方法注入
publicclassUser{ privateStringname; publicvoidsetName(Stringname) { this.name = name; } } Useruser = newUser(); user.setName("abcde");
- 使用接口的方法
publicinterfaceDao { publicvoidassignVal(Stringname); } publicclassDaoImplimplementsDao { privateStringname; publicvoidassignVal(Stringname) { this.name = name; } }
- set method(*)
<!-- Use set method to inject property value --> <beanid="book"class="com.liyiandxuegang.property.Book"> <!-- set value --> <propertyname="bookName"value="Test Value 2" /> </bean>
- Constructor method
// bean.xml <!-- Useconstructortoinjectpropertyvalue --> <beanid="propertyDemo1"class="com.liyiandxuegang.property.PropertyDemo1"> <!-- Injectvalue --> <constructor-argname="userName"value="Test Value" /> </bean> // PropertyDemo1.javapublicclassPropertyDemo1 { privateStringuserName; publicPropertyDemo1(StringuserName) { this.userName = userName; } publicvoidtest1() { System.out.println("demo1--------test1()-------" + userName); } } // TestIoC.java@TestpublicvoidtestDemo1() { ApplicationContextapplicationContext = newClassPathXmlApplicationContext("bean1.xml"); PropertyDemo1propertyDemo1 = (PropertyDemo1) applicationContext.getBean("propertyDemo1"); propertyDemo1.test1(); }
###注入对象类型的属性
- Create class (Servcie and Dao)
在Service里面把dao作为类型属性;
生成dao类型属性的set方法
//1. Define a UserDao fieldprivateUserDaouserDao; //2. generate setmethodpublicvoidsetUserDao(UserDaouserDao) { this.userDao = userDao; }
- 在配置文件中完成这个关系
<!-- 注入对象类型的属性 --><!-- 1. 配置Service和Dao的对象 --> <beanid="userDao"class="com.liyiandxuegang.ioc.UserDao" /> <beanid="userService"class="com.liyiandxuegang.ioc.UserService"> <!-- Inject dao obj name: service类里面属性的名称 ref: dao配置bean标签的id值--> <propertyname="userDao"ref="userDao"></property> </bean>
- Test
@TestpublicvoidtestUserService() { ApplicationContextapplicationContext = newClassPathXmlApplicationContext("bean1.xml"); UserServiceuserService = (UserService) applicationContext.getBean("userService"); userService.addService(); }
<beansxmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- Use P namespace inject --> <beanid="person"class="com.liyiandxuegang.property.Person"p:pname="Name Value" />
- Array, List, Map, Properties
<!-- Inject complicated data value --> <beanid="personComplicated"class="com.liyiandxuegang.property.Person"> <!-- array --> <propertyname="arraysStrings"> <list> <value>Eric</value> <value>Mike</value> <value>Jim</value> </list> </property> <propertyname="list"> <list> <value>Eric List</value> <value>Mike List</value> <value>Jim List</value> </list> </property> <propertyname="map"> <map> <entrykey="aa"value="Eric aa" /> <entrykey="bb"value="Mike BB" /> </map> </property> <propertyname="properties"> <props> <propkey="driverClass">com.mysql.jdbc.Driver</prop> <propkey="username">root</prop> </props> </property> </bean>
IOC:控制反转,把对象创建交个spring进行配置。
DI:依赖注入,向类中属性,设置属性值。
关系: 依赖注入不能单独存在,需要在IOC基础上完成操作。
- Loading spring configuration file use lots of resources.???
ApplicationContextapplicationContext = newClassPathXmlApplicationContext("bean1.xml");
##Solution?
把加载配置文件和创建对象过程,在服务器启动时候完成。
ServletContext Object
Listener Object
在服务器启动时,为每个项目创建ServletContext对象,
在ServletContext对象创建时,使用监听器可以监听到ServletContext对象在创建
使用监听器听到ServletContext对象创建时,加载spring的配置文件,把配置文件配置对象创建。
把创建出来的对象方法ServletContext的域对象里面
获取对象时,到ServletContext域得到
代码里特殊的标记,使用注解也可以完成一些功能。
注解写法:@注解名称(属性名称=属性值)
注解可以使用在类上面,方法上面和属性上面
import spring-aop.jar
Configure xml
<!-- define the package to scan -->
<context:component-scanbase-package="com.liyiandxuegang.anno" />Then add @annotation above the class or field, or function
@Component(value="user") // <bean id="user" class="" />publicclassUser {
publicvoidannoAdd() {
System.out.println("anno Add...."); }
}There are four annotations in Spring:
@Component [as component]
@Controller [Web]
@Service [Service]
@Repository: [Persistence]
功能相同,都是用来创建对象,用来将来对功能的扩展。
###但是控制类的作用范围:scope
@Component(value="user") // <bean id="user" class="" />@Scope(value="prototype")
publicclassUser {
publicvoidannoAdd() {
System.out.println("anno Add...."); }
}- Create class obj
Create UserDao and UserService obje
@Component(value="userDao")
publicclassUserDao {
publicvoidadd() {
System.out.println("dao........add");
}
}
@Service(value="userService")
publicclassUserService {
// define the field of userDao@Autowired//自动注入的方法,找类的名字来注入类属性 (1)privateUserDaouserDao;
// Resource second way: but this time, the value of name should be the same as the objects.@Resource(name="userDao2")
privateUserDao2userDao2; publicvoidadd() {
System.out.println("Service.add ========");
userDao.add();
}
}Use @Resource should be good.
创建对象操作使用配置文件方式实现;
注入属性的操作使用注解方式实现。
Suppose, we have three classes, BookService, BookDao.class, OrdersDao.class
In xml file,
<context:component-scanbase-package="com.liyiandxuegang.xmlanno" />
<beanid="bookService"class="com.liyiandxuegang.xmlanno.BookService" /> <!--BookService bookService <bean id="ordersDao" class="com.liyiandxuegang.xmlanno.OrdersDao" /> <!--OrdersDao ordersDao-->
<beanid="bookDao"class="com.liyiandxuegang.xmlanno.BookDao" /> <!--BookDao bookDao-->In BookService.java file
publicclassBookService {
@Resource(name="bookDao")
privateBookDaobookDao;
@Resource(name="ordersDao")
privateOrdersDaoordersDao;
publicvoidadd() {
System.out.println("bookService ..... add");
bookDao.book();
ordersDao.order();
}
}Then, we can test it, use the Bean to create the class.
ApplicationContextapplicationContext = newClassPathXmlApplicationContext("bean3.xml");
BookServicebookService = (BookService)applicationContext.getBean("bookService");publicclassUser{
// Add userpublicvoidadd(Useruser) {
// code ...
}
}
// extends the function// add user, then add logging function.纵向体系的问题:比如父类方法名称发生了变化,在子类调用的方法也需要变化。
底层使用:动态代理方式实现
- One way (with inteface)
publicinterfaceDao{
publicvoidadd();
}
[使用动态代理方式,创建接口实现代理对象]
publicclassDaoImplimplementsDao{
publicvoidadd() {
// code ....
}
}
// 增强add方法,创建和DaoImpl类平级对象,这个对象不是真正的对象,代理对象实现和DaoImpl相同的功能。// Use JDK dynamic proxy.- Second way (without interface) 使用cglib动态代理,没有接口
// user classpublicclassUser{
publicvoidadd() {
}
}
// 动态代理实现, 创建User类的子类的代理对象// 在子类中也可以调用父类的方法,完成增强Pointcut
Advice:通知或者增强
前置通知:在方法执行之前,执行
后置通知:在方法之后执行
异常通知:方法出现异常之后
最终通知:在后置之后执行
环绕通知:在方法之前和之后来执行。
- Aspect: 切面
把增强应用到具体的方法上,这个过程称为切面。
// Basic classpublicclassUser{
publicvoidadd() {}
publicvoidupdate() {}
publicvoiddelete() {}
publicvoidfindAll() {}
}
// 连接点Jointpoint:类里面那些方法可以被增强,这些方法称为连接点。// 切入点Aspectpoint:在类里面可以有很多的方法增强,比如实际操作中,只是增强了类中add方法和update方法,实际增强的方法称为切入点。// Advice: 通知或者增强- 在spring里面进行AOP操作,使用AspectJ介绍
Spring 2.0, add AspectJ plugin.
- 使用aspectJ实现AOP操作,有两种方式:
*基于AspectJ的xml配置方式
*基于AspectJ的注解方式
Import basic jars, and import aop jars,
Create spring xml, import aop schema.
Use Expression to configuration aspect point.
Mainly used expressions:
execution(public|private|* com.liyiandxuegang.aop.Book.add(..))
execution(* com.liyiandxuegang.aop.Book.*(..))
execution(* .(...))
execution( save*(..)): the methods with save starting.
How to configure? Read the following code:
<!-- 配置对象 -->
<beanid="book"class="com.liyiandxuegang.aop.Book" />
<beanid="myBook"class="com.liyiandxuegang.aop.MyBook" />
<!-- 配置aop操作 -->
<aop:config>
<!-- 1. 配置切入点 -->
<aop:pointcutexpression="execution(* com.liyiandxuegang.aop.Book.*(..))"id="pointcut1" />
<!-- 2. 配置切面 把增强用到方法上-->
<aop:aspectref="myBook">
<!-- 配置增强的类型 method: 增强的类中使用那个方法作为前置增强-->
<aop:beforemethod="before1"pointcut-ref="pointcut1" />
</aop:aspect>
</aop:config>In the code level, we don't need to do anything different. The only thing you need to do is in the xml file.
<!-- 配置对象 -->
<beanid="bookaop"class="com.liyiandxuegang.aop.Book" />
<beanid="myBookaop"class="com.liyiandxuegang.aop.MyBook" />
<!-- 配置aop操作 -->
<aop:config>
<!-- 1. 配置切入点 -->
<aop:pointcutexpression="execution(* com.liyiandxuegang.aop.Book.*(..))"id="pointcut1"></aop:pointcut>
<!-- 2. 配置切面 把增强用到方法上-->
<aop:aspectref="myBookaop">
<!-- 配置增强的类型 method: 增强的类中使用那个方法作为前置增强-->
<aop:beforemethod="before1"pointcut-ref="pointcut1"></aop:before>
<aop:after-returningmethod="after"pointcut-ref="pointcut1"/>
<aop:aroundmethod="around"pointcut-ref="pointcut1"/>
</aop:aspect>
</aop:config>In around method, we need to call ProceedingJoinPoint method for function call.
日志的一个工具,通过log4j能够看到程序中更详细的信息。经常使用log4j查看日志
导入log4j的jar包
复制log4j的配置文件, 复制到src目录下。
- action 调用service, service调用dao, 需要使用struts2的内容。