JavaEE之-Spring详解
2017-10-31 13:19
453 查看
1:导入war包到bin。
2:Spring读取所有文件都是在一个xml配置的工厂里面。所以需要创建一个beans.xml文件,并拷贝相应的schema。
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
3:创建一个类
package
spring01;
public class
HelloWorld {
public
String hello() {
return
"HelloWorld";
}
}
4:在beans.xml中创建这个对象
<!-- 创建如下bean相当于创建了:HelloWorld hello = new HelloWorld() ,如果在bean中没有做scope的配置,默认是singleton(单利),把scope设置为prototype则为多例-->
<!--
注意:一般当状态修改不做任何变化的情况下 就用单例。例如 service、dao。
对于action而言,里面的属性值的状态会根据不同的线程得到不同的值 。所以应该使用多例。
-->
<bean
id =
"hello" class
= "spring01.HelloWorld"
scope
= "prototype/singleton" />
5:在测试类中使用这个对象
public class
TestHelloWorld{
//创建Spring工厂
private
BeanFactory factory =
new
ClassPathXmlApplicationContext("beans.xml");
//通过工厂获取Spring对象
//此处getBean中的hello就是beans.xml中的bean中的id
HelloWorld hello =
factory.getBean("hello",HelloWorld.class);
//或者
HelloWorld hello = (HelloWorld)factory.getBean("hello");
//此时的HelloWorld中的对象就是被Spring所管理的对象
System.out.println(hello.hello());
}
IOC(控制反转): 注意:为什么不用new,而用依赖注入呢。因为new依赖于实现类,当要修改的时候需要全部修改。如果用依赖注入修改的时候只需要改配置文件就可以了。
将所有的类在beans.xml中创建,对有依赖的类完成注入。
Set注入:为每一个依赖类创建相应的get、set方法,并且在配置文件的bean内添加 property属性,使用property就是使用set注入。
<bean
id =
"userAction" class
=
"spring01.action.UserAction"
scope =
"prototype">
<!--
name中的值会在userAction中调用setXXX方法完成注入,例如:name = "userServiceImpl" ,
在具体调用时会调用setUserServiceImpl(UserService userServiceImpl)来完成注入。
ref中的值为配置文件中bean所创建的id名称,例如: ref = "userService",
这个userService为bean中创建的id名
-->
<property name
= "userServiceImpl"
ref
= "userService"
/>
</bean>
<bean
id =
"userService" class
=
"spring01.userService.impl.userServiceImpl">
<!--
name中的值会在userService中调用setXXX方法完成注入,例如:name = "userDao" ,
在具体调用时会调用setUserDaoImpl(UserDao userDaoImpl)来完成注入。
ref中的值为配置文件中bean所创建的id名称,例如: ref = "userDao",
这个userDao为bean中创建的id名
-->
<property
name
= "userDaoImpl"
ref =
"userDao" ></property>
</bean>
<bean id
=
"userDao" class
= "spring01.userDao.impl.UserDaoImpl"/>
Set注入属性并设置值:
<!--创建了一个User对象user,id为“1
”,username为“悟空”。如果要注入值不适用ref,而是用value(ref是引用,value是设值)-->
<bean
id =
"user" class
= "spring01.action.User">
<property
name
= "id"
value
= "1"
/>
<property
name
= "username"
value =
"悟空" />
</bean>
构造方法注入:创建依赖类为参数的构造方法,并在bean内添加“constructor-arg”
属性,在”constructor-arg”中添加ref属性,
设置ref属性值,ref中的值为配置文件中bean所创建的id名称。
<bean
id =
"userAction" class
=
"spring01.action.UserAction"
scope =
"prototype">
<!--
ref中的值为配置文件中bean所创建的id名称,例如: ref = "userService",
这个userService为bean中创建的id名
-->
<constructor-arg ref
=
"userService" />
</bean>
自动注入:为每一个依赖类创建相应的get、set方法,并且在配置文件的bean中添加“autowire”属性。
<!--
autowire = "default" 表示不自动注入,autowire = "byName" 表示根据name来自动注入,
autowire = "byType" 表示根据类型来注入(使用byType注入,如果一个类中有两个同类型的对象,就会报错)
所以在开发中一般都是使用byName,虽然自动注入可以减少配置,但是通过bean文件无法了解整个类的结构,所以不建议使用。
因为根本不知道该类中用到了哪些实现类。
-->
<bean
id
= "userService"
class
= "spring01.service.impl.UserServiceImpl"
autowire="byType"
/>
使用annotation(注解)方式依赖注入:
<?xml
version="1.0"
encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- 打开spring的annotation(注解) -->
<context:annotation-config
/>
<!--设定spring去那些包中找annotation(注解) -->
<context:component-scan
base-package="spring02"
/>
</beans>
在实现类中设bean:
在类名上方添加注解@Component("xxx") //公共的创建bean的annotation
//等于完成了<bean id = "userDao" class = "spring02.dao.impl.UserDaoImpl"/>
@Component("userDao"/"userService"/"userDao")
//设置单例或多例
@Scope("singleton"/"prototype")
在spring3.0之后建议使用
@Controller("userAction") //一般用于
@Service("userService") //一般用于业务层
@Repository("userDAO") //(Repository【工厂】)一般用于DAO的注入
在实现类中添加依赖注入注解:注意(@autowired 自动注入,不推荐使用,因为默认通过类型来注入的)
在实现类中的依赖对象的set方法上添加注解@Resource,默认通过类型来注入。(在JSR330中提供了:@Inject来注入,需要导入包)
AOP(面向切面编程):
1:导入war包到bin。
2:Spring读取所有文件都是在一个xml配置的工厂里面。所以需要创建一个beans.xml文件,并拷贝相应的schema。
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
3:创建一个类
package
spring01;
public class
HelloWorld {
public
String hello() {
return
"HelloWorld";
}i
}
4:在beans.xml中创建这个对象
<!-- 创建如下bean相当于创建了:HelloWorld hello = new HelloWorld() ,
class: bean的全类名,通过反射的方式在IOC容器中创建Bean,所以要求Bean中必须带有无参构造器。
id:标识容器bean,id唯一。
如果在bean中没有做scope的配置,默认是singleton(单利),把scope设置为prototype则为多例-->
<!--
注意:一般当状态修改,不做任何变化的情况下 就用单例。例如 service、dao。
对于action而言,里面的属性值的状态会根据不同的线程得到不同的值 。所以应该使用多例。
-->
<bean
id =
"hello" class
= "spring01.HelloWorld"
scope
= "prototype/singleton" />
5:在测试类中使用这个对象
public class
TestHelloWorld{
//创建Spring工厂
private
BeanFactory factory =
new
ClassPathXmlApplicationContext("beans.xml");
//通过工厂获取Spring对象
//此处getBean中的hello就是beans.xml中的bean中的id
HelloWorld hello =
factory.getBean("hello",HelloWorld.class);
//或者
HelloWorld hello = (HelloWorld)factory.getBean("hello");
//此时的HelloWorld中的对象就是被Spring所管理的对象
System.out.println(hello.hello());
}
IOC(控制反转): 注意:为什么不用new,而用依赖注入呢。因为new依赖于实现类,当要修改的时候需要全部修改。如果用依赖注入修改的时候只需要改配置文件就可以了。
将所有的类在beans.xml中创建,对有依赖的类完成注入。
Set注入:为每一个依赖类创建相应的get、set方法,并且在配置文件的bean内添加 property属性,使用property就是使用set注入。
<bean
id =
"userAction" class
=
"spring01.action.UserAction"
scope =
"prototype">
<!--
name中的值会在userAction中调用setXXX方法完成注入,例如:name = "userServiceImpl" ,
在具体调用时会调用setUserServiceImpl(UserService userServiceImpl)来完成注入。
ref中的值为配置文件中bean所创建的id名称,例如: ref = "userService",
这个userService为bean中创建的id名
-->
<property name
= "userServiceImpl"
ref
= "userService"
/>
</bean>
<bean
id =
"userService" class
=
"spring01.userService.impl.userServiceImpl">
<!--
name中的值会在userService中调用setXXX方法完成注入,例如:name = "userDao" ,
在具体调用时会调用setUserDaoImpl(UserDao userDaoImpl)来完成注入。
ref中的值为配置文件中bean所创建的id名称,例如: ref = "userDao",
这个userDao为bean中创建的id名
-->
<property
name
= "userDaoImpl"
ref =
"userDao" ></property>
</bean>
<bean id
=
"userDao" class
= "spring01.userDao.impl.UserDaoImpl"/>
Set注入属性并设置值:
<!--创建了一个User对象user,id为“1
”,username为“悟空”。如果要注入值不适用ref,而是用value(ref是引用,value是设值)-->
<bean
id =
"user" class
= "spring01.action.User">
<property
name
= "id"
value
= "1"
/>
<property
name
= "username"
value =
"悟空" />
</bean>
构造方法注入:创建依赖类为参数的构造方法,并在bean内添加“constructor-arg”
属性,在”constructor-arg”中添加ref属性,
设置ref属性值,ref中的值为配置文件中bean所创建的id名称。
<bean
id =
"userAction" class
=
"spring01.action.UserAction"
scope =
"prototype">
<!--
ref中的值为配置文件中bean所创建的id名称,例如: ref = "userService",
这个userService为bean中创建的id名
-->
<constructor-arg ref
=
"userService" />
</bean>
自动注入:为每一个依赖类创建相应的get、set方法,并且在配置文件的bean中添加“autowire”属性。
<!--
autowire = "default" 表示不自动注入,autowire = "byName" 表示根据name来自动注入,
autowire = "byType" 表示根据类型来注入(使用byType注入,如果一个类中有两个同类型的对象,就会报错)
所以在开发中一般都是使用byName,虽然自动注入可以减少配置,但是通过bean文件无法了解整个类的结构,所以不建议使用。
因为根本不知道该类中用到了哪些实现类。
-->
<bean
id
= "userService"
class
= "spring01.service.impl.UserServiceImpl"
autowire="byType"
/>
bean的继承和依赖:
继承:bean之间的继承分两种,
1、bean实例:如果子bean要继承父bean,则在子bean中配置parent属性,并设置属性值为父bean的id。
2、bean模板:如果子bean要继承父bean,则在子bean中配置abstract属性,并设置属性值为true。注释:如果配置bean模板,则不用声明class地址。
依赖:在bean中配置属性:depends-on 前置依赖,并设置依赖bean实例,如有多个,可用逗号隔开。
bean的作用域:
默认情况下在IOC容器中配置的bean的对象是单利的。
使用bean的scope属性来配置bean的作用域。
singleton:单利 默认,在整个生命周期内,只创建这一个bean。在容器初始化时已经被创建。
prototype:多利 原型的。在容器初始化时不会被创建,而是每次请求时,都会创建一个新的bean实例。
在 spring整合status2的时候需要配置bean的scope为prototype。
spring引入外部属性文件:
spring提供了一个PropertyPlaceholderConfigurer的BeanFactory后置处理器,这个后置处理器允许用户将Bean配置的部分内容外移到属性文件中。可以在Bean配置文件里使用形式为${var}的变量。
在Spring2.5之后:可以通过<context:property-placehoder location location="classpath:db.properties"/>
Spring生命周期:
1、通过构造器或工厂方法创建Bean实例
2、为Bean的属性设置值和对其他Bean的引用
3、调用Bean的初始化方法
4、Bean可以使用了
5、当容器调用close关闭时,调用Bean的销毁方法
通过在Bean里声明init-method和destroy-mentod属性,为Bean指定初始化和销毁方法。
通过工厂方法配置Bean:
静态工厂方法:直接调用某个类的静态方法就可以返回Bean的实例。在Bean中添加factory-method属性,来调用静态方法,参数通过<constructor-ags value=""/>来配置。
如果仅希望扫描特定的类,而非基包下的所有类,可以使用resource-pattern属性过滤特定类。
![](https://img-blog.csdn.net/20171031132120859?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMTA3NjQ3NQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](https://img-blog.csdn.net/20171031132150520?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMTA3NjQ3NQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
实例工厂方法:实例工厂的方法,即先创建工厂本身,在调用工厂实例方法来返回Bean的实例。
![](https://img-blog.csdn.net/20171031132214398?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMTA3NjQ3NQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](https://img-blog.csdn.net/20171031132238570?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMTA3NjQ3NQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
使用annotation(注解)方式依赖注入:
在classpath中扫描组件(componentscanning):spring能够从classpath下自动扫描,检测和实例化具有特定注解的组件:
特定组件包括:
@Component:基本注解,标识了一个受Spring管理的组件。
@Respository:标识持久层组件
@Service:标识业务层组件
@Controller:标识表现层组件
基于注解配置Bean:
基于注解来装配Bean的属性:
使用@Autowired注解自动装配具有兼容类型的单个Bean属性(构造器、普通字段、一切具有参数的方法都可以应用@Autowired注解)
默认情况下,所有使用@Autowired注解的属性都需要被设置。当Spring找不到匹配的Bean装配时,会抛出异常,若某一属性允许不被设置,可以设置@Autowired注解的required属性为false。
Spring4.0的新特性:
泛型依赖注入:Spring4.0中可以为子类注入子类对应的泛型类型的成员变量的引用。
![](https://img-blog.csdn.net/20171031132311405?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMTA3NjQ3NQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](https://img-blog.csdn.net/20171031132352777?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMTA3NjQ3NQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
<?xml
version="1.0"
encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!--设定spring去那些包中找annotation(注解) -->
<context:component-scan
base-package="spring02"
/>
</beans>
在实现类中设bean:
在类名上方添加注解@Component("xxx") //公共的创建bean的annotation
//等于完成了<bean id = "userDao" class = "spring02.dao.impl.UserDaoImpl"/>
@Component("userDao"/"userService"/"userDao")
//设置单例或多例
@Scope("singleton"/"prototype")
在spring3.0之后建议使用
@Controller("userAction") //一般用于MVC的控制层
@Service("userService") //一般用于业务层
@Repository("userDAO") //(Repository【工厂】)一般用于DAO的注入
在实现类中添加依赖注入注解:注意(@autowired 自动注入,不推荐使用,因为默认通过类型来注入的)
在实现类中的依赖对象的set方法上添加注解@Resource,默认通过名称来注入。(在JSR330中提供了:@Inject来注入,需要导入包)
为什么要使用AOP?
代码混乱:如加入日志和验证等,会使原有的业务方法急剧膨胀,每个方法在处理核心逻辑的同时还必须兼顾其他多个关注点。
代码分散:如果日志需求发生变化,必须修改所有模块。
AOP(面向切面编程):
将与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护下。
AOP优点:
1、每个事物逻辑位于一个位置,代码不分散,便于维护和升级。
2、业务模块更简洁,只包含核心业务代码。
使用场景:
Authentication 权限,Caching 缓存,Context passing 内容传递,Error handing 错误处理,Lazy loading 懒加载,Debugging 调试,Presistence 持久化,Synchronization 同步,Transactions 事物。
核心概念:
1.横切关注点:对哪些方法进行拦截,拦截后如何处理,这些关注点称为横切关注点。
2.切面(aspect) 类是对物体特征的抽象,切面就是对横切关注点的抽象。
3.连接点(joinpoint)被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器。
4.切入点(pointcut)对连接点进行拦截的定义。
5.通知(advice)所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕,五类。
6.目标对象:代理目标对象。
7.织入(weave)将切面应用到目标对象并导致代理对象创建的过程。
8.引入(introduction)在不修改代码的前提下,引入可以在运行期为类动态的添加一些方法或字段。
AOP切面的优先级:
在切面类中添加下面注解属性:
@Oreder(1),值越小,优先级越高。
Spring对AOP的支持:
Spring中AOP代理由Spring的IOC容器负责生成、管理,其依赖关系也由IOC容器负责管理。(因此,AOP代理可以直接使用容器中的其他bean实例作为目标,这种关系可以由IOC容器的依赖注入提供)
1、默认使用Java动态代理来创建AOP代理,这样就可以为任何借口实例创建代理了。
2、当需要代理的类不是代理接口的时候,Spring会切换使用CGLIB代理。
基于Spirng实现简单的动态代理:(动态代理指的是通过一个代理对象来创建需要的业务对象,然后在这个代理对象中统一进行各种需求的处理)(使用一个代理对象包装起来,然后用该代理对象取代原始对象。任何对原始对象的调用都要通过代理,代理对象决定是否以及和是将方法调用转到原始对象上。)
![](https://img-blog.csdn.net/20171031132441801?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMTA3NjQ3NQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
package
spring02.logger
/**
* 创建logger日志类
*/
public class
Logger{
public static void
info(String str){
System.out.println(new
SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new
Date())+"---"+str);
}
}
package
spring02.proxy;
import
java.lang.reflect.InvocationHandler;
import
java.lang.reflect.Method;
import
java.lang.reflect.Proxy;
import
spring02.logger.Logger;
/**
* 动态代理类(写一个类实现InvocationHandler接口)
*
*/
public class
LogProxy
implements
InvocationHandler{
private
LogProxy(){};
//1、创建一个代理对象 target
private
Object
target
;
//2、创建一个方法来生成对象,这个方法的参数是要代理的对象,getInstance返回的对象就是代理对象。
public static
Object getInstance( Object o ){
//3.1、创建LogProxy对象
LogProxy proxy =
new
LogProxy();
//3.2、设置这个代理对象
proxy.target
= o ;
//3.3、通过Proxy方法创建代理对象,
// 第一个参数是原对象的classLoder,
// 第二个参数是原对象实现的所有接口,
// 第三个参数是实现类InvocationHandler的对象
Object result = Proxy.newProxyInstance(o.getClass.getClassLoder(),o.getClass.getInterfaces(),proxy);
return
result;
}
/**
* 当有了代理对象之后,不管这个代理对象执行什么方法,都会调用invoke方法
*/
@Override
public
Object invoke(Object proxy , Method mothod, Object[] args)
throws
Throwable{
Logger.info("进行了相应的操作");
Object obj = method.invoke(target,args);
return
obj;
}
}
<?xml
version="1.0"
encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- 打开spring的annotation(注解)
-->
<context:annotation-config />
<!--设定spring去那些包中找annotation(注解)
-->
<context:component-scan
base-package="spring02"
/>
<bean
id
=
"userDynamicDao"
class
="spring02.proxy.LogProxy"
factory-method="getInstance">
<constructor-arg
ref="userDao"/>
</bean>
</beans>
Spring基于 Annotation实现AOP:
添加AOP的scheam
打开Spring AOP Annotation扫描
添加Spring AOP第三方 jar 包:aspectjrt.jar,aspectjweaver.jar,aopalliance.jar
<?xml
version="1.0"
encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop
= "http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<!-- 打开spring的annotation(注解)支持
-->
<context:annotation-config
/>
<!--设定spring去那些包中找annotation(注解)
-->
<context:component-scan
base-package="spring02"
/>
<bean
id
=
"userDynamicDao"
class
="spring02.proxy.LogProxy"
factory-method="getInstance">
<constructor-arg
ref="userDao"/>
</bean>
<!-- 打开spring的aop自动检索
-->
<aop:aspectj-autoproxy/>
</beans>
package
spring02.proxy;
import
org.aspectj.lang.JoinPoint;
import
org.aspectj.lang.annotation.After;
import
org.aspectj.lang.annotation.Aspect;
import
org.aspectj.lang.annotation.Before;
import
org.springframework.stereotype.Component;
import
spring02.logger.Logger;
/**
* 创建log日志切面
* @author Super
*
*/
//设bean,让这个类被spring管理
@Component("logAspect")
//声明这个类是一个切面类
@Aspect
public class
LogAspect {
/*
* 创建通知(开始的时候加入)
*/
@Before("execution(* spring02.dao.*.add(..))")
public void
logStart(JoinPoint jp){
//得到执行的对象
System.out.println(jp.getTarget());
//得到执行对象的方法
System.out.println(jp.getSignature().getName());
Logger.info("加入日志");
}
@After("execution(* spring02.dao.*.add(..))")
public void
logEnd(){
Logger.info("加入日志");
}
}
Spring基于 XML实现AOP:
添加AOP的scheam
添加Spring AOP第三方 jar 包:aspectjrt.jar,aspectjweaver.jar,aopalliance.jar
<?xml
version="1.0"
encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<!-- 开启Spring IOC注解 -->
<context:annotation-config/>
<!-- 告诉Spring去哪个包里找注解 -->
<context:component-scan
base-package="spring03"/>
<!-- 常规方式实现AOP动态代理 -->
<!--
<bean id = "userDynamicServlce" class = "spring03.proxy.LogProxy" factory-method="getInstance">
<constructor-arg ref="userService"/>
</bean>
-->
<!-- 开启Spring AOP 第三方注解 -->
<!-- <aop:aspectj-autoproxy/> -->
<aop:config>
<!-- 定义切面 可以有多个切面 -->
<aop:aspect
ref="logAspect">
<!--pointcut属性表示在哪个地方加入相应的aspect,参数中
第一个*标识任意返回值 -->
<aop:pointcut
id="logPointcut"
expression="execution(* spring03.dao.impl.*.*add(..))"
/>
<aop:before
method="logStartProxy"
pointcut-ref="logPointcut"/>
</aop:aspect>
</aop:config>
</beans>
package
spring03.proxy;
import
org.springframework.stereotype.Component;
import
spring03.logger.Logger;
@Component("logAspect")
public class
LogAspect {
public void
logStartProxy(){
Logger.info("XML Aspect 开始。。");
}
public void
logEndProxy(){
Logger.info("XML Aspect 结束。。");
}
}
Spring事务管理:
声明式事物:
<!-- 开启Spring 事物管理 -->
<bean
id ="transactionManager"
class
= " org.springframework.jdbc.datasource.DataSourceTransactionManager ">
<property
name =
"datasource" ref
= "datasource"/>
</bean>
<!-- 启用事物管理-->
<tx:annocation-driver
transaction-manager
= "transactionmanager"
/>
在Service实现类的对应的方法上添加@Transactional注解。
基于XML方式配置事物:
<!--配置事物管理器-->
<bean id="transactionManager" class = "org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref = "datasource"/>
</bean>
<!--配置事物属性-->
<tx:advice
id="txadvice"
transaction-manager
= "transactionManager">
<tx:attributes>
<tx:method
name="*"/>
</tx:attributes>
</tx:advice>
<!--配置事物切入点,以及把事物切入点和事物属性关联起来-->
<aop:config>
<aop:pointcut
expression="execution(* *add*(..))"
id="txPointCut"/>
<aop:advisor
advice-ref="txAdvice"
pointcut-ref
= "txPointCut"/>
</aop:config>
2:Spring读取所有文件都是在一个xml配置的工厂里面。所以需要创建一个beans.xml文件,并拷贝相应的schema。
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
3:创建一个类
package
spring01;
public class
HelloWorld {
public
String hello() {
return
"HelloWorld";
}
}
4:在beans.xml中创建这个对象
<!-- 创建如下bean相当于创建了:HelloWorld hello = new HelloWorld() ,如果在bean中没有做scope的配置,默认是singleton(单利),把scope设置为prototype则为多例-->
<!--
注意:一般当状态修改不做任何变化的情况下 就用单例。例如 service、dao。
对于action而言,里面的属性值的状态会根据不同的线程得到不同的值 。所以应该使用多例。
-->
<bean
id =
"hello" class
= "spring01.HelloWorld"
scope
= "prototype/singleton" />
5:在测试类中使用这个对象
public class
TestHelloWorld{
//创建Spring工厂
private
BeanFactory factory =
new
ClassPathXmlApplicationContext("beans.xml");
//通过工厂获取Spring对象
//此处getBean中的hello就是beans.xml中的bean中的id
HelloWorld hello =
factory.getBean("hello",HelloWorld.class);
//或者
HelloWorld hello = (HelloWorld)factory.getBean("hello");
//此时的HelloWorld中的对象就是被Spring所管理的对象
System.out.println(hello.hello());
}
IOC(控制反转): 注意:为什么不用new,而用依赖注入呢。因为new依赖于实现类,当要修改的时候需要全部修改。如果用依赖注入修改的时候只需要改配置文件就可以了。
将所有的类在beans.xml中创建,对有依赖的类完成注入。
Set注入:为每一个依赖类创建相应的get、set方法,并且在配置文件的bean内添加 property属性,使用property就是使用set注入。
<bean
id =
"userAction" class
=
"spring01.action.UserAction"
scope =
"prototype">
<!--
name中的值会在userAction中调用setXXX方法完成注入,例如:name = "userServiceImpl" ,
在具体调用时会调用setUserServiceImpl(UserService userServiceImpl)来完成注入。
ref中的值为配置文件中bean所创建的id名称,例如: ref = "userService",
这个userService为bean中创建的id名
-->
<property name
= "userServiceImpl"
ref
= "userService"
/>
</bean>
<bean
id =
"userService" class
=
"spring01.userService.impl.userServiceImpl">
<!--
name中的值会在userService中调用setXXX方法完成注入,例如:name = "userDao" ,
在具体调用时会调用setUserDaoImpl(UserDao userDaoImpl)来完成注入。
ref中的值为配置文件中bean所创建的id名称,例如: ref = "userDao",
这个userDao为bean中创建的id名
-->
<property
name
= "userDaoImpl"
ref =
"userDao" ></property>
</bean>
<bean id
=
"userDao" class
= "spring01.userDao.impl.UserDaoImpl"/>
Set注入属性并设置值:
<!--创建了一个User对象user,id为“1
”,username为“悟空”。如果要注入值不适用ref,而是用value(ref是引用,value是设值)-->
<bean
id =
"user" class
= "spring01.action.User">
<property
name
= "id"
value
= "1"
/>
<property
name
= "username"
value =
"悟空" />
</bean>
构造方法注入:创建依赖类为参数的构造方法,并在bean内添加“constructor-arg”
属性,在”constructor-arg”中添加ref属性,
设置ref属性值,ref中的值为配置文件中bean所创建的id名称。
<bean
id =
"userAction" class
=
"spring01.action.UserAction"
scope =
"prototype">
<!--
ref中的值为配置文件中bean所创建的id名称,例如: ref = "userService",
这个userService为bean中创建的id名
-->
<constructor-arg ref
=
"userService" />
</bean>
自动注入:为每一个依赖类创建相应的get、set方法,并且在配置文件的bean中添加“autowire”属性。
<!--
autowire = "default" 表示不自动注入,autowire = "byName" 表示根据name来自动注入,
autowire = "byType" 表示根据类型来注入(使用byType注入,如果一个类中有两个同类型的对象,就会报错)
所以在开发中一般都是使用byName,虽然自动注入可以减少配置,但是通过bean文件无法了解整个类的结构,所以不建议使用。
因为根本不知道该类中用到了哪些实现类。
-->
<bean
id
= "userService"
class
= "spring01.service.impl.UserServiceImpl"
autowire="byType"
/>
使用annotation(注解)方式依赖注入:
<?xml
version="1.0"
encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- 打开spring的annotation(注解) -->
<context:annotation-config
/>
<!--设定spring去那些包中找annotation(注解) -->
<context:component-scan
base-package="spring02"
/>
</beans>
在实现类中设bean:
在类名上方添加注解@Component("xxx") //公共的创建bean的annotation
//等于完成了<bean id = "userDao" class = "spring02.dao.impl.UserDaoImpl"/>
@Component("userDao"/"userService"/"userDao")
//设置单例或多例
@Scope("singleton"/"prototype")
在spring3.0之后建议使用
@Controller("userAction") //一般用于
@Service("userService") //一般用于业务层
@Repository("userDAO") //(Repository【工厂】)一般用于DAO的注入
在实现类中添加依赖注入注解:注意(@autowired 自动注入,不推荐使用,因为默认通过类型来注入的)
在实现类中的依赖对象的set方法上添加注解@Resource,默认通过类型来注入。(在JSR330中提供了:@Inject来注入,需要导入包)
AOP(面向切面编程):
1:导入war包到bin。
2:Spring读取所有文件都是在一个xml配置的工厂里面。所以需要创建一个beans.xml文件,并拷贝相应的schema。
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
3:创建一个类
package
spring01;
public class
HelloWorld {
public
String hello() {
return
"HelloWorld";
}i
}
4:在beans.xml中创建这个对象
<!-- 创建如下bean相当于创建了:HelloWorld hello = new HelloWorld() ,
class: bean的全类名,通过反射的方式在IOC容器中创建Bean,所以要求Bean中必须带有无参构造器。
id:标识容器bean,id唯一。
如果在bean中没有做scope的配置,默认是singleton(单利),把scope设置为prototype则为多例-->
<!--
注意:一般当状态修改,不做任何变化的情况下 就用单例。例如 service、dao。
对于action而言,里面的属性值的状态会根据不同的线程得到不同的值 。所以应该使用多例。
-->
<bean
id =
"hello" class
= "spring01.HelloWorld"
scope
= "prototype/singleton" />
5:在测试类中使用这个对象
public class
TestHelloWorld{
//创建Spring工厂
private
BeanFactory factory =
new
ClassPathXmlApplicationContext("beans.xml");
//通过工厂获取Spring对象
//此处getBean中的hello就是beans.xml中的bean中的id
HelloWorld hello =
factory.getBean("hello",HelloWorld.class);
//或者
HelloWorld hello = (HelloWorld)factory.getBean("hello");
//此时的HelloWorld中的对象就是被Spring所管理的对象
System.out.println(hello.hello());
}
IOC(控制反转): 注意:为什么不用new,而用依赖注入呢。因为new依赖于实现类,当要修改的时候需要全部修改。如果用依赖注入修改的时候只需要改配置文件就可以了。
将所有的类在beans.xml中创建,对有依赖的类完成注入。
Set注入:为每一个依赖类创建相应的get、set方法,并且在配置文件的bean内添加 property属性,使用property就是使用set注入。
<bean
id =
"userAction" class
=
"spring01.action.UserAction"
scope =
"prototype">
<!--
name中的值会在userAction中调用setXXX方法完成注入,例如:name = "userServiceImpl" ,
在具体调用时会调用setUserServiceImpl(UserService userServiceImpl)来完成注入。
ref中的值为配置文件中bean所创建的id名称,例如: ref = "userService",
这个userService为bean中创建的id名
-->
<property name
= "userServiceImpl"
ref
= "userService"
/>
</bean>
<bean
id =
"userService" class
=
"spring01.userService.impl.userServiceImpl">
<!--
name中的值会在userService中调用setXXX方法完成注入,例如:name = "userDao" ,
在具体调用时会调用setUserDaoImpl(UserDao userDaoImpl)来完成注入。
ref中的值为配置文件中bean所创建的id名称,例如: ref = "userDao",
这个userDao为bean中创建的id名
-->
<property
name
= "userDaoImpl"
ref =
"userDao" ></property>
</bean>
<bean id
=
"userDao" class
= "spring01.userDao.impl.UserDaoImpl"/>
Set注入属性并设置值:
<!--创建了一个User对象user,id为“1
”,username为“悟空”。如果要注入值不适用ref,而是用value(ref是引用,value是设值)-->
<bean
id =
"user" class
= "spring01.action.User">
<property
name
= "id"
value
= "1"
/>
<property
name
= "username"
value =
"悟空" />
</bean>
构造方法注入:创建依赖类为参数的构造方法,并在bean内添加“constructor-arg”
属性,在”constructor-arg”中添加ref属性,
设置ref属性值,ref中的值为配置文件中bean所创建的id名称。
<bean
id =
"userAction" class
=
"spring01.action.UserAction"
scope =
"prototype">
<!--
ref中的值为配置文件中bean所创建的id名称,例如: ref = "userService",
这个userService为bean中创建的id名
-->
<constructor-arg ref
=
"userService" />
</bean>
自动注入:为每一个依赖类创建相应的get、set方法,并且在配置文件的bean中添加“autowire”属性。
<!--
autowire = "default" 表示不自动注入,autowire = "byName" 表示根据name来自动注入,
autowire = "byType" 表示根据类型来注入(使用byType注入,如果一个类中有两个同类型的对象,就会报错)
所以在开发中一般都是使用byName,虽然自动注入可以减少配置,但是通过bean文件无法了解整个类的结构,所以不建议使用。
因为根本不知道该类中用到了哪些实现类。
-->
<bean
id
= "userService"
class
= "spring01.service.impl.UserServiceImpl"
autowire="byType"
/>
bean的继承和依赖:
继承:bean之间的继承分两种,
1、bean实例:如果子bean要继承父bean,则在子bean中配置parent属性,并设置属性值为父bean的id。
2、bean模板:如果子bean要继承父bean,则在子bean中配置abstract属性,并设置属性值为true。注释:如果配置bean模板,则不用声明class地址。
依赖:在bean中配置属性:depends-on 前置依赖,并设置依赖bean实例,如有多个,可用逗号隔开。
bean的作用域:
默认情况下在IOC容器中配置的bean的对象是单利的。
使用bean的scope属性来配置bean的作用域。
singleton:单利 默认,在整个生命周期内,只创建这一个bean。在容器初始化时已经被创建。
prototype:多利 原型的。在容器初始化时不会被创建,而是每次请求时,都会创建一个新的bean实例。
在 spring整合status2的时候需要配置bean的scope为prototype。
spring引入外部属性文件:
spring提供了一个PropertyPlaceholderConfigurer的BeanFactory后置处理器,这个后置处理器允许用户将Bean配置的部分内容外移到属性文件中。可以在Bean配置文件里使用形式为${var}的变量。
在Spring2.5之后:可以通过<context:property-placehoder location location="classpath:db.properties"/>
Spring生命周期:
1、通过构造器或工厂方法创建Bean实例
2、为Bean的属性设置值和对其他Bean的引用
3、调用Bean的初始化方法
4、Bean可以使用了
5、当容器调用close关闭时,调用Bean的销毁方法
通过在Bean里声明init-method和destroy-mentod属性,为Bean指定初始化和销毁方法。
通过工厂方法配置Bean:
静态工厂方法:直接调用某个类的静态方法就可以返回Bean的实例。在Bean中添加factory-method属性,来调用静态方法,参数通过<constructor-ags value=""/>来配置。
如果仅希望扫描特定的类,而非基包下的所有类,可以使用resource-pattern属性过滤特定类。
实例工厂方法:实例工厂的方法,即先创建工厂本身,在调用工厂实例方法来返回Bean的实例。
使用annotation(注解)方式依赖注入:
在classpath中扫描组件(componentscanning):spring能够从classpath下自动扫描,检测和实例化具有特定注解的组件:
特定组件包括:
@Component:基本注解,标识了一个受Spring管理的组件。
@Respository:标识持久层组件
@Service:标识业务层组件
@Controller:标识表现层组件
基于注解配置Bean:
基于注解来装配Bean的属性:
使用@Autowired注解自动装配具有兼容类型的单个Bean属性(构造器、普通字段、一切具有参数的方法都可以应用@Autowired注解)
默认情况下,所有使用@Autowired注解的属性都需要被设置。当Spring找不到匹配的Bean装配时,会抛出异常,若某一属性允许不被设置,可以设置@Autowired注解的required属性为false。
Spring4.0的新特性:
泛型依赖注入:Spring4.0中可以为子类注入子类对应的泛型类型的成员变量的引用。
<?xml
version="1.0"
encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!--设定spring去那些包中找annotation(注解) -->
<context:component-scan
base-package="spring02"
/>
</beans>
在实现类中设bean:
在类名上方添加注解@Component("xxx") //公共的创建bean的annotation
//等于完成了<bean id = "userDao" class = "spring02.dao.impl.UserDaoImpl"/>
@Component("userDao"/"userService"/"userDao")
//设置单例或多例
@Scope("singleton"/"prototype")
在spring3.0之后建议使用
@Controller("userAction") //一般用于MVC的控制层
@Service("userService") //一般用于业务层
@Repository("userDAO") //(Repository【工厂】)一般用于DAO的注入
在实现类中添加依赖注入注解:注意(@autowired 自动注入,不推荐使用,因为默认通过类型来注入的)
在实现类中的依赖对象的set方法上添加注解@Resource,默认通过名称来注入。(在JSR330中提供了:@Inject来注入,需要导入包)
为什么要使用AOP?
代码混乱:如加入日志和验证等,会使原有的业务方法急剧膨胀,每个方法在处理核心逻辑的同时还必须兼顾其他多个关注点。
代码分散:如果日志需求发生变化,必须修改所有模块。
AOP(面向切面编程):
将与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护下。
AOP优点:
1、每个事物逻辑位于一个位置,代码不分散,便于维护和升级。
2、业务模块更简洁,只包含核心业务代码。
使用场景:
Authentication 权限,Caching 缓存,Context passing 内容传递,Error handing 错误处理,Lazy loading 懒加载,Debugging 调试,Presistence 持久化,Synchronization 同步,Transactions 事物。
核心概念:
1.横切关注点:对哪些方法进行拦截,拦截后如何处理,这些关注点称为横切关注点。
2.切面(aspect) 类是对物体特征的抽象,切面就是对横切关注点的抽象。
3.连接点(joinpoint)被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器。
4.切入点(pointcut)对连接点进行拦截的定义。
5.通知(advice)所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕,五类。
6.目标对象:代理目标对象。
7.织入(weave)将切面应用到目标对象并导致代理对象创建的过程。
8.引入(introduction)在不修改代码的前提下,引入可以在运行期为类动态的添加一些方法或字段。
AOP切面的优先级:
在切面类中添加下面注解属性:
@Oreder(1),值越小,优先级越高。
Spring对AOP的支持:
Spring中AOP代理由Spring的IOC容器负责生成、管理,其依赖关系也由IOC容器负责管理。(因此,AOP代理可以直接使用容器中的其他bean实例作为目标,这种关系可以由IOC容器的依赖注入提供)
1、默认使用Java动态代理来创建AOP代理,这样就可以为任何借口实例创建代理了。
2、当需要代理的类不是代理接口的时候,Spring会切换使用CGLIB代理。
基于Spirng实现简单的动态代理:(动态代理指的是通过一个代理对象来创建需要的业务对象,然后在这个代理对象中统一进行各种需求的处理)(使用一个代理对象包装起来,然后用该代理对象取代原始对象。任何对原始对象的调用都要通过代理,代理对象决定是否以及和是将方法调用转到原始对象上。)
package
spring02.logger
/**
* 创建logger日志类
*/
public class
Logger{
public static void
info(String str){
System.out.println(new
SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new
Date())+"---"+str);
}
}
package
spring02.proxy;
import
java.lang.reflect.InvocationHandler;
import
java.lang.reflect.Method;
import
java.lang.reflect.Proxy;
import
spring02.logger.Logger;
/**
* 动态代理类(写一个类实现InvocationHandler接口)
*
*/
public class
LogProxy
implements
InvocationHandler{
private
LogProxy(){};
//1、创建一个代理对象 target
private
Object
target
;
//2、创建一个方法来生成对象,这个方法的参数是要代理的对象,getInstance返回的对象就是代理对象。
public static
Object getInstance( Object o ){
//3.1、创建LogProxy对象
LogProxy proxy =
new
LogProxy();
//3.2、设置这个代理对象
proxy.target
= o ;
//3.3、通过Proxy方法创建代理对象,
// 第一个参数是原对象的classLoder,
// 第二个参数是原对象实现的所有接口,
// 第三个参数是实现类InvocationHandler的对象
Object result = Proxy.newProxyInstance(o.getClass.getClassLoder(),o.getClass.getInterfaces(),proxy);
return
result;
}
/**
* 当有了代理对象之后,不管这个代理对象执行什么方法,都会调用invoke方法
*/
@Override
public
Object invoke(Object proxy , Method mothod, Object[] args)
throws
Throwable{
Logger.info("进行了相应的操作");
Object obj = method.invoke(target,args);
return
obj;
}
}
<?xml
version="1.0"
encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- 打开spring的annotation(注解)
-->
<context:annotation-config />
<!--设定spring去那些包中找annotation(注解)
-->
<context:component-scan
base-package="spring02"
/>
<bean
id
=
"userDynamicDao"
class
="spring02.proxy.LogProxy"
factory-method="getInstance">
<constructor-arg
ref="userDao"/>
</bean>
</beans>
Spring基于 Annotation实现AOP:
添加AOP的scheam
打开Spring AOP Annotation扫描
添加Spring AOP第三方 jar 包:aspectjrt.jar,aspectjweaver.jar,aopalliance.jar
<?xml
version="1.0"
encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop
= "http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<!-- 打开spring的annotation(注解)支持
-->
<context:annotation-config
/>
<!--设定spring去那些包中找annotation(注解)
-->
<context:component-scan
base-package="spring02"
/>
<bean
id
=
"userDynamicDao"
class
="spring02.proxy.LogProxy"
factory-method="getInstance">
<constructor-arg
ref="userDao"/>
</bean>
<!-- 打开spring的aop自动检索
-->
<aop:aspectj-autoproxy/>
</beans>
package
spring02.proxy;
import
org.aspectj.lang.JoinPoint;
import
org.aspectj.lang.annotation.After;
import
org.aspectj.lang.annotation.Aspect;
import
org.aspectj.lang.annotation.Before;
import
org.springframework.stereotype.Component;
import
spring02.logger.Logger;
/**
* 创建log日志切面
* @author Super
*
*/
//设bean,让这个类被spring管理
@Component("logAspect")
//声明这个类是一个切面类
@Aspect
public class
LogAspect {
/*
* 创建通知(开始的时候加入)
*/
@Before("execution(* spring02.dao.*.add(..))")
public void
logStart(JoinPoint jp){
//得到执行的对象
System.out.println(jp.getTarget());
//得到执行对象的方法
System.out.println(jp.getSignature().getName());
Logger.info("加入日志");
}
@After("execution(* spring02.dao.*.add(..))")
public void
logEnd(){
Logger.info("加入日志");
}
}
Spring基于 XML实现AOP:
添加AOP的scheam
添加Spring AOP第三方 jar 包:aspectjrt.jar,aspectjweaver.jar,aopalliance.jar
<?xml
version="1.0"
encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<!-- 开启Spring IOC注解 -->
<context:annotation-config/>
<!-- 告诉Spring去哪个包里找注解 -->
<context:component-scan
base-package="spring03"/>
<!-- 常规方式实现AOP动态代理 -->
<!--
<bean id = "userDynamicServlce" class = "spring03.proxy.LogProxy" factory-method="getInstance">
<constructor-arg ref="userService"/>
</bean>
-->
<!-- 开启Spring AOP 第三方注解 -->
<!-- <aop:aspectj-autoproxy/> -->
<aop:config>
<!-- 定义切面 可以有多个切面 -->
<aop:aspect
ref="logAspect">
<!--pointcut属性表示在哪个地方加入相应的aspect,参数中
第一个*标识任意返回值 -->
<aop:pointcut
id="logPointcut"
expression="execution(* spring03.dao.impl.*.*add(..))"
/>
<aop:before
method="logStartProxy"
pointcut-ref="logPointcut"/>
</aop:aspect>
</aop:config>
</beans>
package
spring03.proxy;
import
org.springframework.stereotype.Component;
import
spring03.logger.Logger;
@Component("logAspect")
public class
LogAspect {
public void
logStartProxy(){
Logger.info("XML Aspect 开始。。");
}
public void
logEndProxy(){
Logger.info("XML Aspect 结束。。");
}
}
Spring事务管理:
声明式事物:
<!-- 开启Spring 事物管理 -->
<bean
id ="transactionManager"
class
= " org.springframework.jdbc.datasource.DataSourceTransactionManager ">
<property
name =
"datasource" ref
= "datasource"/>
</bean>
<!-- 启用事物管理-->
<tx:annocation-driver
transaction-manager
= "transactionmanager"
/>
在Service实现类的对应的方法上添加@Transactional注解。
基于XML方式配置事物:
<!--配置事物管理器-->
<bean id="transactionManager" class = "org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref = "datasource"/>
</bean>
<!--配置事物属性-->
<tx:advice
id="txadvice"
transaction-manager
= "transactionManager">
<tx:attributes>
<tx:method
name="*"/>
</tx:attributes>
</tx:advice>
<!--配置事物切入点,以及把事物切入点和事物属性关联起来-->
<aop:config>
<aop:pointcut
expression="execution(* *add*(..))"
id="txPointCut"/>
<aop:advisor
advice-ref="txAdvice"
pointcut-ref
= "txPointCut"/>
</aop:config>
相关文章推荐
- JavaEE开发之Spring中的多线程编程以及任务定时器详解(有源码)
- JavaEE框架——Springmvc入门(注解URL核心类详解、文件上传和下载)、和Spring的整合
- JavaEE开发之Spring中的多线程编程以及任务定时器详解
- JavaEE开发之Spring中的多线程编程以及任务定时器详解
- JavaEE开发之Spring中的多线程编程以及任务定时器详解
- JavaEE开发之Spring中的多线程编程以及任务定时器详解
- JAVAEE之Spring学习(五)---SpringMVC注解实现功能的详解
- 关于spring3.0注解详解
- 详解Spring中bean生命周期回调方法
- JAVAEE之Spring学习(五)---目前开发所用的springMVC的架构思想
- struts spring hibernate 搭建(详解)
- spring mybatis多数据源实例详解
- MyBatis详解 与配置MyBatis+Spring+MySql
- spring详解(六)自定义注解2
- Spring Data JPA实体详解(二)
- spring配置文件详解--真的蛮详细
- 详解spring 每个jar的作用
- 详解Spring简单容器中的Bean基本加载过程
- Spring3.0 AOP 详解
- spring+springmvc+mybatis中的xml配置文件详解