Spring学习笔记

摘抄自(http://www.cnblogs.com/cyjch/archive/2012/02/06/2340415.html)

首先需要准备Spring包,可从官方网站上下载。

下载解压后,必须的两个包是spring.jar和commons-logging.jar。此外为了便于测试加入了JUnit包。

在Myeclipse中创建Java项目。

编写一个接口类,为了简单,只加入了一个方法。

Java代码
1.package com.szy.spring.interfacebean;
2.
3.public interface PersonBean
4.{
5. void show();
6.}

然后写一个类实现这个接口。

Java代码
1.package com.szy.spring.implbean;
2.import com.szy.spring.interfacebean.PersonBean;
3.
4.public class UserBean implements PersonBean
5.{
6.
7. public void show()
8. {
9. System.out.println(“Hello Kuka”);
10. }
11.
12.}

以上的过程我们再熟悉不过了,下面开始加入Spring的内容了。首先从下载的Sping包中找到配置文件,删除不需要的,找到最原始的部分:

Xml代码
1.

Sping学习笔记(2)—-实例化Bean的三种方式

Spring的实例化Bean有三种方式:

使用类构造器直接实例化

使用静态工厂的方法实例化

使用实例工厂方法实例化

三种方式对应的配置如下

Xml代码
1.

Spring学习笔记(3)—-编码剖析Spring管理Bean的原理

Xml代码
1.

Spring学习笔记(4)—-Bean节点信息配置

默认情况下,Spring的Ioc容器启动时会初始化bean,但是我们可以指定Bean节点的lazy-init=”true”,来延迟初始化bean。这时候,只有第一次获取bean才会初始化bean。如

Xml代码
1.

如果想对所有的bean有应用延迟初始化,可以在跟节点beans设置default-lazy-init=”true”,如下:

Xml代码
1.

此外,如果我们还想UserBean在实例化是调用初始化方法时,我们可以加入“init-method=”init””属性,其中init为Userbean中的init()方法,与之对应,“destroy-method=”destroy””为销毁属性。

在Spring中我们通过getBean(name)方法获得实例,那么我们每次获取的实例化对象是一个还是多个呢?

我们可以通过“==”进行测试

Java代码
1.ApplicationContext ctx=new ClassPathXmlApplicationContext(“applicationContext.xml”);
2.PersonBean bean1=(PersonBean)ctx.getBean(“userBean”);
3.PersonBean bean2=(PersonBean)ctx.getBean(“userBean”);
4.System.out.println(bean1==bean2);

运行输出结果为:true

这说明了Bean交给sping容器管理之后,Bean默认情况下是单实例的。

如果我们想每次通过getBean(name)方法获得实例是一个新的实例化对象该怎么办呢?

在配置文件中节点bean有一个属性scope,只要我们配置如下即可:

Xml代码
1.

在运行测试代码,输出结果为:false

Spring学习笔记(5)—-依赖注入的简单实现

Spring的核心机制是依赖注入。依赖注入让bean与bean之间以配置文件组织在一起,而不是以硬编码的方式耦合在一起。依赖注入(Dependency Injection)和控制反转(Inversion of Control)是同一个概念。具体含义是:当某个角色(可能是一个Java实例,调用者)需要另一个角色(另一个Java实例,被调用者)的协助时,在传统的程序设计过程中,通常由调用者来创建被调用者的实例。但在Spring里,创建被调用者的工作不再由调用者来完成,因此称为控制反转;创建被调用者实例的工作通常由Spring容器来完成,然后注入调用者,因此也称为依赖注入。管是依赖注入,还是控制反转,都说明Spring采用动态、灵活的方式来管理各种对象。对象与对象之间的具体实现互相透明。

下面通过简单的实例演示依赖注入。

项目中主要包含一下一个文件:

UserDAO是一个接口,包含了一个方法:

Java代码
1.package com.szy.spring.dao;
2.
3.public interface UserDAO
4.{
5. void show();
6.}

而UserDAO4MySqlImpl和UserDAO4OracleImpl实现了UserDAO中的方法。

Java代码
1.package com.szy.spring.dao;
2.public class UserDAO4MySqlImpl implements UserDAO
3.{
4. public void show()
5. {
6. System.out.println(“MySqlDAO Implement”);
7. }
8.}

Java代码
1.package com.szy.spring.dao;
2.public class UserDAO4OracleImpl implements UserDAO
3.{
4. public void show()
5. {
6. System.out.println(“OracleDAO Implement”);
7. }
8.}

UserService是另外一个包中的接口,

Java代码
1.package com.szy.spring.service;
2.
3.public interface UserService
4.{
5. void show();
6.}

UserServiceImpl实现了这个接口,

Java代码
1.package com.szy.spring.service;
2.
3.import com.szy.spring.dao.UserDAO;
4.
5.public class UserServiceImpl implements UserService
6.{
7. private UserDAO userDAO;
8.
9. public void show()
10. {
11. userDAO.show();
12. }
13.
14. public UserDAO getUserDAO()
15. {
16. return userDAO;
17. }
18. public void setUserDAO(UserDAO userDAO)
19. {
20. this.userDAO = userDAO;
21. }
22.}

但是在实现这个接口中,调用了UserDAO中的方法。一般情况下我们需要在这里实例化一个UserDAO对象,比如

Java代码
1.UserDAO userDAO=new UserDAO4MySqlImpl();

这样的话耦合度就比较高,通过spring我们可以降低耦合度。

在Sping的配置文件中,我们需要这样配置

Java代码
1.

Spring学习笔记(6)—-编码剖析Spring依赖注入的原理

在Spring学习笔记(3)中剖析了Spring管理Bean的原理,下面解释下Spring依赖注入的原理

在进行依赖注入时,我们的配置文件如下配置:

Xml代码
1.

Spring学习笔记(7)—-装配各种集合类型的属性

前面已经介绍了如何给属性注入对象,下面介绍一下如何装配集合类型的属性
1.Set类型

Java代码
1.private Set sets=new HashSet();
2.//我们需要给它添加set方法
3.public Set getSets()
4. {
5. return sets;
6. }
7. public void setSets(Set sets)
8. {
9. this.sets = sets;
10. }
11.public Set showSet()
12. {
13. return sets;
14. }

然后根据属性修改配置文件

Xml代码
1.
2.
3.
4. Set1
5. Set2
6. Set3
7.
8.
9.
10.

与以前不同的是我们在property下面添加了

这样就能装配set类型的属性

2.List类型

List类型的属性和Set类型的方法一样,主要是把配置文件中的set修改成list。

Java代码
1.private List lists=new ArrayList();
2.public List getLists()
3. {
4. return lists;
5. }
6. public void setLists(List lists)
7. {
8. this.lists = lists;
9. }
10.public List showList()
11. {
12. return lists;
13. }

配置文件修改如下

Xml代码
1.
2.
3.
4. List1
5. List2
6. List3
7.
8.
9.

3.Properties类型

Java代码
1.private Properties properties=new Properties();
2.public void setProperties(Properties properties)
3. {
4. this.properties = properties;
5. }
6.public Properties getProperties()
7. {
8. return properties;
9. }
10.public Properties showProperties()
11. {
12. return properties;
13. }

配置文件需要如下配置

Xml代码
1.
2.
3.
4. Properties1
5. Properties2
6. Properties3
7.
8.
9.
10.

4.Map类型

Java代码
1.private Map

Spring学习笔记(8)—-属性注入的方式

Spring中属性注入的方式有三种:

1.使用属性setter方法注入

2.使用构造器注入

3.使用注解方式注入

使用属性setter方法注入

使用属性setter方法注入就是给属性添加set()方法,在前面都是使用这种方法。

Java代码
1.package com.szy.spring.service;
2.
3.import com.szy.spring.dao.PersonDao;
4.
5.public class UserServiceImplBySetter implements UserService
6.{
7. private PersonDao personDao;
8.
9. public void show()
10. {
11. personDao.show();
12. }
13. public PersonDao getPersonDao()
14. {
15. return personDao;
16. }
17. public void setPersonDao(PersonDao personDao)
18. {
19. this.personDao = personDao;
20. }
21.}

然后在配置文件中如下配置

Xml代码
1.
2.
3.
4.
5.

使用构造器注入

使用构造器注入就是在类中添加含参构造函数

Java代码
1.package com.szy.spring.service;
2.
3.import com.szy.spring.dao.PersonDao;
4.
5.public class UserServiceImplConstructor implements UserService
6.{
7. private PersonDao personDao;
8. private String name;
9.
10. public UserServiceImplConstructor()
11. {
12. }
13.
14. public UserServiceImplConstructor(PersonDao personDao, String name)
15. {
16. this.personDao = personDao;
17. this.name = name;
18. }
19.
20. public void show()
21. {
22. personDao.show();
23. System.out.println(“name属性:”+name);
24. }
25.}

下面就是在配置文件中添加配置信息,给每个参数注入值

Xml代码
1.
2.
3.
4.
5.
6.

注意:constructor-arg index是从0开始的

使用注解方式注入

如果使用前面的两种方法,配置文件将会显得很臃肿,因此我们可以使用注解的方式注入,使用注解方式注入有两种方法,第一种使用javax.annotation.Resource中提供的注解方式方法如下:

Java代码
1.package com.szy.spring.service;
2.
3.import javax.annotation.Resource;
4.
5.import com.szy.spring.dao.PersonDao;
6.
7.public class UserServiceImplByAnnotation4Resource implements UserService
8.{
9. //@Resource默认是按照名称装配,找不到与名称匹配的bean时按类型装配
10. @Resource(name=”personDao”)private PersonDao personDao;
11.
12. public void show()
13. {
14. personDao.show();
15. }
16.// 下面方法同样可以
17.// @Resource
18.// public void setPersonDao(PersonDao personDao)
19.// {
20.// this.personDao = personDao;
21.// }
22.
23.}

此时配置文件要做相应的改变

Xml代码
1.

Spring学习笔记(9)—-让Spring自动扫描和管理Bean

Java代码
1.package com.szy.spring.service;
2.
3.import org.springframework.stereotype.Service;
4.
5.import com.szy.spring.dao.PersonDao;
6.@Service(“service”)
7.public class UserServiceImpl implements UserService
8.{
9. private PersonDao personDaoBean;
10.
11. public void show()
12. {
13. personDaoBean.show();
14. }
15.
16. public void setPersonDaoBean(PersonDao personDaoBean)
17. {
18. this.personDaoBean = personDaoBean;
19. }
20.}

在前面的例子中,都是使用XML的bean定义来使用组件,在大的项目中,通常会有上百个组件,如果这些组件采用xml的bean定义来配置,显然会使配置文件显得很臃肿,查找和维护起来不方便。Spring2.5为我们引入了组件自动扫描机制,它可以在类路径下寻找标记了@Component、@Service、@Controller、@Repository注解的类,并把这些类纳入到spring容器中管理,它的作用和在xml中使用bean节点配置组件一样。要使用自动扫描机制,我们需要把配置文件如下配置:

Xml代码
1.

Spring学习笔记(10)—-公共属性的注入配置

假设我们定义了四个bean类,其代码分别如下:

Java代码
1.package com.szy.spring.bean;
2.
3.public class Bean1 {
4. private Bean2 bean2;
5. private Bean3 bean3;
6. private Bean4 bean4;
7.
8. public Bean2 getBean2()
9. {
10. return bean2;
11. }
12. public void setBean2(Bean2 bean2)
13. {
14. this.bean2 = bean2;
15. }
16. public Bean3 getBean3()
17. {
18. return bean3;
19. }
20. public void setBean3(Bean3 bean3)
21. {
22. this.bean3 = bean3;
23. }
24. public Bean4 getBean4()
25. {
26. return bean4;
27. }
28. public void setBean4(Bean4 bean4)
29. {
30. this.bean4 = bean4;
31. }
32.}

Java代码
1.package com.szy.spring.bean;
2.
3.public class Bean2
4.{
5. private int id;
6. private String name;
7. private String password;
8.
9. public int getId()
10. {
11. return id;
12. }
13. public void setId(int id)
14. {
15. this.id = id;
16. }
17. public String getName()
18. {
19. return name;
20. }
21. public void setName(String name)
22. {
23. this.name = name;
24. }
25. public String getPassword()
26. {
27. return password;
28. }
29. public void setPassword(String password)
30. {
31. this.password = password;
32. }
33.}

Java代码
1.package com.szy.spring.bean;
2.
3.public class Bean3
4.{
5. private int id;
6. private String name;
7.
8. public int getId()
9. {
10. return id;
11. }
12. public void setId(int id)
13. {
14. this.id = id;
15. }
16. public String getName()
17. {
18. return name;
19. }
20. public void setName(String name)
21. {
22. this.name = name;
23. }
24.}

Java代码
1.package com.szy.spring.bean;
2.
3.public class Bean4
4.{
5. private int age;
6.
7. public int getAge()
8. {
9. return age;
10. }
11. public void setAge(int age)
12. {
13. this.age = age;
14. }
15.}

按照正常的思路,我们下面就要给每个类进行属性的注入,配置文件如下设置:

Xml代码
1.

Spring学习笔记(11)—-自定义属性编辑器

前面我们所定义的属性都是几本的属性,如果我们定义一个属性是Date类型,例如如下类中:

Java代码
1.package com.szy.spring.bean;
2.
3.import java.util.Date;
4.
5.public class Bean {
6. private Date date;
7.
8. public Date getDate()
9. {
10. return date;
11. }
12. public void setDate(Date date)
13. {
14. this.date = date;
15. }
16.}

按照我们以前学过的知识我们需要在配置文件中给该属性注入值

Xml代码
1.
2.
3.

下面我们测试是否成功注入值

Java代码
1.ApplicationContext ctx=new ClassPathXmlApplicationContext(“applicationContext.xml”);
2. Bean bean = (Bean)ctx.getBean(“bean”);
3. System.out.println(bean.getDate());

运行包如下异常

Exception代码
1.org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘bean’ defined in class path resource [applicationContext.xml]: Initialization of bean failed; nested exception is org.springframework.beans.TypeMismatchException: Failed to convert property value of type [java.lang.String] to required type [java.util.Date] for property ‘date’; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type [java.lang.String] to required type [java.util.Date] for property ‘date’: no matching editors or conversion strategy found

通过错误提示信息我们得知spring不能将string转换成date类型,没有匹配的编辑器或者转换机制。
如果想实现string转换成Date,那么我们自己需要写一个属性编辑器

我们新建一个类DatePropertyEditor,这个类要继承PropertyEditorSupport类。
我们需要复写这个类中的setAsText方法,其中text参数就是配置文件中的值。我们的任务就是把text转换成date类型的值。

Java代码
1.package com.szy.spring.util;
2.
3.import java.beans.PropertyEditorSupport;
4.import java.text.SimpleDateFormat;
5.import java.util.Date;
6.
7.public class DatePropertyEditor extends PropertyEditorSupport
8.{
9.
10. @Override
11. public void setAsText(String text) throws IllegalArgumentException
12. {
13. String format=”yyyy-MM-dd”;
14. SimpleDateFormat sdf=new SimpleDateFormat(format);
15. try
16. {
17. Date date=sdf.parse(text);
18. this.setValue(date); //把转换后的值传过去
19. } catch (Exception e)
20. {
21. e.printStackTrace();
22. }
23. }
24.
25.}

写完编辑器后我们还需要把编辑器注入到spring中。 为了方便管理我们再新建一个配置文件applicationEditor.xml,用来配置属性编辑器

Xml代码
1.

Spring学习笔记(12)—-静态代理模式分析演示

代理模式分为静态代理和动态代理。静态代理就是我们自己定义的代理类,动态代理是程序在运行时生成的代理类。

下面演示下静态代理类。首先我们要定义一个接口:

Java代码
1.package com.szy.spring;
2.
3.public interface UserManager
4.{
5. public void addUser(String username,String password);
6. public void deleteUser(int userId);
7. public void modifyUser(int userId,String username,String password);
8. public void findUser(int userId);
9.}

比较常见的对用户进行增删改查。

下面我们常见一个实现类,实现这个接口。

Java代码
1.package com.szy.spring;
2.
3.public class UserManagerImpl implements UserManager
4.{
5.
6. public void addUser(String username, String password)
7. {
8. System.out.println(“——–UserManagerImpl.addUser()———-“);
9. }
10.
11. public void deleteUser(int userId)
12. {
13. System.out.println(“——–UserManagerImpl.deleteUser()———-“);
14. }
15.
16. public void findUser(int userId)
17. {
18. System.out.println(“——–UserManagerImpl.findUser()———-“);
19. }
20.
21. public void modifyUser(int userId, String username, String password)
22. {
23. System.out.println(“——–UserManagerImpl.modifyUser()———-“);
24. }
25.}

每个方法仅仅是输出一句话。

下面我们定义一个客户端类来调用这些方法。

Java代码
1.package com.szy.spring;
2.
3.public class Client
4.{
5. public static void main(String[] args)
6. {
7. UserManager userManager=new UserManagerImpl();
8. userManager.addUser(“coolszy”, “kuka”);
9. }
10.}

运行正常输出我们期望的结果。

下面我们需要加入安全性检查,就是调用方法前我们需要进行验证,比较常见的就是权限验证,验证用户是否拥有权限,

比较常见的做法就是在UserManagerImpl类中定义一个检查安全性的方法:

Java代码
1.public void checkSecurity()
2. {
3. System.out.println(“——–UserManagerImpl.checkSecurity()———-“);
4. }

然后在每个方法中都要调用这个方法。但是这样不符合开-闭原则(Open-Closed principle,简称OCP)。因此我们可以使用代理类来实现这个功能。代理模式很显著的特征就是和目标对象的接口一致。在代理类中我们可以控制目标对象。要控制目标对象我们必须有一个目标对象的引用。为了灵活我们可以把目标对象传到方法中,而不是在方法中实例化。同时我们把安全性检查的代码也放到代理类中,在调用每个方法之前调用这个检查方法,通过代理对我们以前的类没有破坏。

Java代码
1.package com.szy.spring;
2.
3.public class UserManagerImplProxy implements UserManager
4.{
5. private UserManager userManager;
6.
7. public UserManagerImplProxy(UserManager userManager)
8. {
9. this.userManager = userManager;
10. }
11. public void addUser(String username, String password)
12. {
13. checkSecurity();
14. this.userManager.addUser(username, password);
15. }
16. public void deleteUser(int userId)
17. {
18. checkSecurity();
19. this.userManager.deleteUser(userId);
20. }
21. public String findUser(int userId)
22. {
23. checkSecurity();
24. return this.userManager.findUser(userId);
25. }
26. public void modifyUser(int userId, String username, String password)
27. {
28. checkSecurity();
29. this.userManager.modifyUser(userId, username, password);
30. }
31. public void checkSecurity()
32. {
33. System.out.println(“——–UserManagerImpl.checkSecurity()———-“);
34. }
35.}

下面修改客户端类。

Java代码
1.UserManager userManager=new UserManagerImplProxy(new UserManagerImpl());
2. userManager.addUser(“coolszy”, “kuka”);

这样总的来说比较灵活。这个依赖关系是我们自己做的,我们完全可以交给spring处理。

按照上面的这种做法有一个缺点,如果接口中方法很多,那么我们实现每一个方法都要添加检查方法checkSecurity(),影响了我们的业务处理。采用静态代理模式我们是没法解决的,这时我们需要使用AOP思想。

Spring学习笔记(13)—-动态代理模式分析演示

上一节演示的是静态代理模式,本节演示的是静态代理模式,既然是动态,那么就不存在UserManagerImplProxy类。

使用动态代理我们需要声明一个类SecurityHandler,这个类要实现InvocationHandler接口。

在类中定义一个产生动态代理的方法newProxy();同时把我们验证的代码放到这个类中。通过SecurityHandler,当我们调用方法时默认会调用SecurityHandler类invoke方法,我们在这个方法中进行安全性检查,检查通过后在调用真实的方法。需要注意的是目标对象接口中的部分方法是存在返回值的。

Java代码
1.package com.szy.spring;
2.
3.import java.lang.reflect.InvocationHandler;
4.import java.lang.reflect.Method;
5.import java.lang.reflect.Proxy;
6.
7.public class SecurityHandler implements InvocationHandler
8.{
9. private Object targetObject;
10.
11. public Object newProxy(Object targetObject)
12. {
13. this.targetObject=targetObject;
14. //返回动态代理
15. return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
16. targetObject.getClass().getInterfaces(),
17. this);
18. }
19. public Object invoke(Object proxy, Method method, Object[] args)
20. throws Throwable
21. {
22. checkSecurity();
23. Object ret=null;
24. try
25. {
26. //调用目标对象的真实方法
27. ret=method.invoke(this.targetObject, args);
28. //ret接受存在的返回值,不存在返回值则为Null
29. } catch (Exception e)
30. {
31. e.printStackTrace();
32. }
33. return null;
34. }
35. public void checkSecurity()
36. {
37. System.out.println(“——–UserManagerImpl.checkSecurity()———-“);
38. }
39.}

使用这种方式维护起来相对比较好,我想进行安全性检查就进行,不想就不进行,很方便。

下面进行客户端调用

Java代码
1.package com.szy.spring;
2.
3.public class Client
4.{
5. public static void main(String[] args)
6. {
7. SecurityHandler handler=new SecurityHandler();
8. //创建代理对象
9. UserManager userManager=(UserManager)handler.newProxy(new UserManagerImpl());
10. userManager.addUser(“coolszy”, “kuka”);
11. }
12.}

Spring学习笔记(14)—-使用CGLIB实现AOP功能

接着这上面的例子,在上面的例子中我们的UserManagerImpl类是实现了UserManager接口,如果UserManagerImpl没有实现任何接口要怎么办呢?应为创建代理对象时我们需要指定接口的。

Java代码
1.Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
2. targetObject.getClass().getInterfaces(),
3. this);

由于没有时间接口,因此我们是不能这样创建代理接口的,这是我们需要借助第三方包来实现。在spring中提供了cglib-nodep-2.1_3.jar包。我们通过cglib创建代理对象。

下面就通过实例演示通过cglib创建代理对象。

首先创建CGlibProxyFactory,实现MethodInterceptor接口,接口中有一个intercept方法,当代理对象的方法被调用时会调用这个方法。

Java代码
1.package com.szy.spring;
2.
3.import java.lang.reflect.Method;
4.import net.sf.cglib.proxy.Enhancer;
5.import net.sf.cglib.proxy.MethodInterceptor;
6.import net.sf.cglib.proxy.MethodProxy;
7.
8.
9.public class CGlibProxyFactory implements MethodInterceptor
10.{
11. private Object targetObject;
12.
13. public Object newProxy(Object targetObject)
14. {
15. this.targetObject=targetObject;
16. Enhancer enhancer=new Enhancer();
17. enhancer.setSuperclass(this.targetObject.getClass());
18. enhancer.setCallback(this);
19. //返回代理对象
20. return enhancer.create();
21. }
22.
23. /**
24. * proxy 带来对象本身
25. * method 被拦截到的方法
26. * args 方法的参数
27. * methodProxy 方法的代理对象
28. */
29. public Object intercept(Object proxy, Method method, Object[] args,
30. MethodProxy methodProxy) throws Throwable
31. {
32. checkSecurity();
33. Object ret=null;
34. try
35. {
36. //调用目标对象的真实方法
37. ret=method.invoke(this.targetObject, args);
38. //ret接受存在的返回值,不存在返回值则为Null
39. } catch (Exception e)
40. {
41. e.printStackTrace();
42. }
43. return ret;
44. }
45. public void checkSecurity()
46. {
47. System.out.println(“——–UserManagerImpl.checkSecurity()———-“);
48. }
49.}

其实整个代码很前面的很相似,只是创建代理对象的方法不一样。

测试代码:

Java代码
1.CGlibProxyFactory factory=new CGlibProxyFactory();
2. //创建代理对象,这是这个代理对象是UserManagerImpl的子类
3. UserManagerImpl userManager=(UserManagerImpl)factory.newProxy(new UserManagerImpl());
4. userManager.addUser(“coolszy”, “kuka”);

上面演示的几个事例是不借助与任何框架的情况下实现AOP的方法。

Spring学习笔记(15)—-使用Spring的注解方式实现AOP

下面介绍使用Spring框架进行AOP编程。

首先我们需要导入需要的jar包:

1.aspectjrt.jar

2.aspectjweaver.jar

3.cglib-nodep-2.1_3.jar

在spring中有两种方式实现面向切面编程,一种是基于XML配置,另一种是使用注解份额方式,在实际开放中我们可以任选其中的一种即可。

首先介绍下使用注解方式进行AOP开发。

要使用注解方式,我们需要打开注解处理器

Xml代码
1.

我们还是使用前面介绍的接口:

Java代码
1.package com.szy.spring;
2.
3.public interface UserManager
4.{
5.
6. public abstract void addUser(String username, String password);
7.
8. public abstract void deleteUser(int userId);
9.
10. public abstract String findUser(int userId);
11.
12. public abstract void modifyUser(int userId, String username, String password);
13.
14.}

实现这个接口:

Java代码
1.package com.szy.spring;
2.
3.public class UserManagerImpl implements UserManager
4.{
5.
6. public void addUser(String username, String password)
7. {
8. System.out.println(“——–UserManagerImpl.addUser()———-“);
9. }
10.
11. public void deleteUser(int userId)
12. {
13. System.out.println(“——–UserManagerImpl.deleteUser()———-“);
14. }
15.
16. public String findUser(int userId)
17. {
18. System.out.println(“——–UserManagerImpl.findUser()———-“);
19. return null;
20. }
21.
22. public void modifyUser(int userId, String username, String password)
23. {
24. System.out.println(“——–UserManagerImpl.modifyUser()———-“);
25. }
26.}

下面我们定义一个切面类,由于我们使用的是注解方式,因此我们使用@Aspect来标识它是切面类。在切面类中我们要定义切入点,切入点是用来定义我们要拦截的方法。在切入点定义中使用了AOP表达式语言,下面通过实例简单解释一下:

表达式解释代码
1.@Pointcut(“execution (* com.szy.spring...(..))”)
2.execution:代表执行
3.第一个:代表返回值类型,使用代表任何类型的返回值
4.com.szy.spring:代表包名
5…:代表其底下的子包也进行拦截
6.第二个:代表对哪个类进行拦截,代表所有类
7.第三个*:代表方法
8.(..):代表方法的蚕食有无都可以

现在我们要对UserManagerImpl类下的所有方法进行拦截,则切入点如下表示:

Java代码
1.@Pointcut(“execution (* com.szy.spring.UserManagerImpl.*(..))”)
2.
3.private void anyMethod() //定义切入点
4. {
5. }

其中切入点的名称是下面方法的名称aynMethod(),包括括号。

下面我们定义通知,通知分为前置通知、后置通知、意外通知、等。通知分为前置通知、后置通知、意外通知、最终通知和环绕通知等。

演示前置通知,

Java代码
1.@Before(“anyMethod()”) //括号内为切入点名称
2. public void doBefore()
3. {
4. System.out.println(“—————-执行前置通知—————–”);
5. }
6.
7. @AfterReturning(“anyMethod()”)
8. public void doAfterReturning()
9. {
10. System.out.println(“—————-执行后置通知—————–”);
11. }

Java代码
1. @After(“anyMethod()”)
2. public void doAfter()
3. {
4. System.out.println(“—————-执行最终通知—————–”);
5. }
6.
7. @AfterThrowing(“anyMethod()”)
8. public void doAfterThrowing()
9. {
10. System.out.println(“—————-执行意外通知—————–”);
11. }
12.
13. @Around(“anyMethod()”)
14. public Object doAround(ProceedingJoinPoint pjp) throws Throwable
15. {
16. System.out.println(“—————-进入判断方法—————–”);
17. Object result=pjp.proceed(); //该方法必须被执行
18. System.out.println(“—————-退出判断方法—————–”);
19. return result;
20. }

我们把切面交给spring管理,要交给spring管理我们可以在配置文件同进行bean配置,或者使用扫描的方式。

Xml代码
1.

下面我们进行测试

Java代码
1.ApplicationContext context=new ClassPathXmlApplicationContext(“applicationContext.xml”);
2. UserManager manager=(UserManager)context.getBean(“userManager”);
3. manager.addUser(“coolszy”, “kuka”);

按照我们的设计,输入的结果应为

—————-执行前置通知—————–
—————-进入判断方法—————–
——–UserManagerImpl.addUser()———-
—————-执行后置通知—————–
—————-执行最终通知—————–
—————-退出判断方法—————–

Spring学习笔记(16)—-使用Spring配置文件实现AOP

前面介绍了使用注解的方式,下面介绍使用配置文件的方式实现AOP。

使用配置方式,Interceptor类中不包含任何注解。

Java代码
1.package com.szy.spring;
2.
3.import org.aspectj.lang.ProceedingJoinPoint;
4.
5.public class Interceptor
6.{
7. public void doBefore()
8. {
9. System.out.println(“—————-执行前置通知—————–”);
10. }
11.
12. public void doAfterReturning()
13. {
14. System.out.println(“—————-执行后置通知—————–”);
15. }
16.
17. public void doAfter()
18. {
19. System.out.println(“—————-执行最终通知—————–”);
20. }
21.
22. public void doAfterThrowing()
23. {
24. System.out.println(“—————-执行意外通知—————–”);
25. }
26.
27. public Object doAround(ProceedingJoinPoint pjp) throws Throwable
28. {
29. System.out.println(“—————-进入判断方法—————–”);
30. Object result=pjp.proceed(); //该方法必须被执行
31. System.out.println(“—————-退出判断方法—————–”);
32. return result;
33. }
34.}

紧着这我们在配置文件中配置切面、切入点、通知等:

Xml代码
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.

运行测试代码输入正常结果。

在实际开发中AOP一般用于权限设置等。

Spring学习笔记(17)—-使用Spring注解方式管理事务

使用Spring+JDBC集成步骤如下:

*配置数据源,例如:

Xml代码
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.

*配置事务,配置事务时,需要在xml配置文件中引入用于声明事务的tx命名空间,事务的配置有两种方式:注解方式和基于XML配置的方式

下面演示下使用Spring注解方式管理事务

首先在配置文件中配置Spring提供的事务管理器

Xml代码
1.
2.
3.
4.

由于会使用注解方式,因此我们要打开注解处理器,对注解进行解析

Xml代码
1.

这样我们的配置文件配置完成,下面我们在Mysql中建立一张表,

Sql代码
1.create table users
2.(
3. id int(11) not null auto_increment,
4. username varchar(20) not null,
5. primary key (id)
6.)

根据数据库,我们创建javabean

Java代码
1.package com.szy.spring.bean;
2./**
3. * @author coolszy
4. * @time Dec 6, 2009 2:13:33 PM
5. */
6.public class User
7.{
8. private int id;
9. private String username;
10. public int getId()
11. {
12. return id;
13. }
14. public void setId(int id)
15. {
16. this.id = id;
17. }
18. public String getUsername()
19. {
20. return username;
21. }
22. public void setUsername(String username)
23. {
24. this.username = username;
25. }
26.}

然后创建DAO接口,在DAO中提供几个方法:

Java代码
1.package com.szy.spring.dao;
2.
3.import java.util.List;
4.
5.import com.szy.spring.bean.User;
6.
7.public interface UserDAO
8.{
9. public void save(User user);
10. public void update(User user);
11. Public User getUser(int id);
12. public void delete(int id);
13. public List getAllUsers();
14.}

实现这个接口

Java代码
1.package com.szy.spring.dao.impl;
2.
3.import java.util.List;
4.
5.import com.szy.spring.bean.User;
6.import com.szy.spring.service.UserService;
7.
8./**
9. * @author coolszy
10. * @time Dec 6, 2009 2:19:22 PM
11. */
12.public class UserDAOImpl implements UserDAO
13.{
14.
15. public void delete(int id)
16. {
17.
18. }
19.
20. public List getAllUsers()
21. {
22. return null;
23. }
24.
25. public User getUser(int id)
26. {
27.
28. }
29.
30. public void save(User user)
31. {
32.
33. }
34.
35. public void update(User user)
36. {
37.
38. }
39.
40.}

下面把这个类交给Spring管理

Xml代码
1.

由于要通过数据源对表进行操作,因此在DAO中添加数据源。

Java代码
1.private DataSource dataSource;
2.
3. public void setDataSource(DataSource dataSource)
4. {
5. this.dataSource = dataSource;
6. }

然后在配置文件中进行配置

Xml代码
1.
2.
3.

这样我们就把数据源注入到类中。

在UserDAOImpl类中我们提供了dataSource,这样我们就可以对数据库进行操作,但是不推荐直接使用dataSource,建议使用JdbcTemplate

Java代码
1.private JdbcTemplate jdbcTemplate;
2. public void setDataSource(DataSource dataSource)
3. {
4. //this.dataSource = dataSource;
5. this.jdbcTemplate=new JdbcTemplate(dataSource);
6. }

下面我们使用jdbcTemplate对数据库进行增删改查,详细代码见附件。

Java代码
1.package com.szy.spring.dao.impl;
2.
3.import java.util.List;
4.
5.import javax.sql.DataSource;
6.
7.import org.springframework.jdbc.core.JdbcTemplate;
8.
9.import com.szy.spring.bean.User;
10.import com.szy.spring.dao.UserDAO;
11.
12./**
13. * @author coolszy
14. * @time Dec 6, 2009 2:19:22 PM
15. */
16.public class UserDAOImpl implements UserDAO
17.{
18. //private DataSource dataSource;
19. private JdbcTemplate jdbcTemplate;
20. public void setDataSource(DataSource dataSource)
21. {
22. //this.dataSource = dataSource;
23. this.jdbcTemplate=new JdbcTemplate(dataSource);
24. }
25.
26. public void delete(int id)
27. {
28. jdbcTemplate.update(“delete from users where id=?”, new Object[]{id},
29. new int[]{java.sql.Types.INTEGER});
30. }
31.
32. public List getAllUsers()
33. {
34. return (List)jdbcTemplate.query(“select * from users”, new UserRowMapper());
35. }
36.
37. public User getUser(int id)
38. {
39. return (User)jdbcTemplate.queryForObject(“select * from users where id=?”, new Object[]{id},
40. new int[]{java.sql.Types.INTEGER}, new UserRowMapper());
41.
42. }
43.
44. public void save(User user)
45. {
46. jdbcTemplate.update(“insert into users(username) values(?)”, new Object[]{user.getUsername()},
47. new int[]{java.sql.Types.VARCHAR});
48.
49. }
50.
51. public void update(User user)
52. {
53. jdbcTemplate.update(“update users set username=? where id=?”, new Object[]{user.getUsername(),user.getId()},
54. new int[]{java.sql.Types.VARCHAR, java.sql.Types.INTEGER});
55.
56. }
57.
58.}

编写测试代码,代码运行正常。

在我们实现的每个方法中如delete()方法,如果delete方法是这样

Java代码
1.public void delete(int id)
2. {
3. jdbcTemplate.update(“delete from users where id=?”, new Object[]{id},
4. new int[]{java.sql.Types.INTEGER});
5.jdbcTemplate.update(“delete from users where id=?”, new Object[]{id},
6. new int[]{java.sql.Types.INTEGER});
7.
8. }
9.

这样每条语句都会在各自的事务中执行,并不能保证在同一使用中执行,为了保证在同一事务中执行,我们应使用Spring容器提供的声明事务,我们在UserDAOImpl 类上加入@Transactional,表示该类受Spring事务管理。如果该类中每个方法不需要事务管理,如getUser方法,则在该方法前加入

Java代码
1.@Transactional(propagation=Propagation.NOT_SUPPORTED)

PS:在上面的配置文件中我们在配置文件中指明了驱动类等信息,如果我们想写在配置文件中要怎么配置能,首先我们编写配置文件,

Jdbc.properties代码
1.driverClassName=com.mysql.jdbc.Driver
2.url=jdbc:mysql://localhost:3306/test
3.username=root
4.password=123456
5.initialSize=1
6.maxActive=100
7.maxIdle=2
8.minIdle=1

然后Spring的配置文件需进行如下配置:

Xml代码
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.

这样就可以从属性文件中读取到配置信息。

Spring学习笔记(18)—-使用Spring配置文件实现事务管理

由于我们要拦截UserDAOImpl中的方法,因此我们需要在配置文件中配置信息,在配置文件中使用了AOP技术来拦截方法。

Xml代码
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.

这样Spring就能对这个类进行事务管理。

下面我们测试下数据库操作是否在同一事务中执行。

假设我们的delete方法如下:

Java代码
1.public void delete(int id)
2. {
3. jdbcTemplate.update(“delete from users where id=?”, new Object[]{id},
4. new int[]{java.sql.Types.INTEGER});
5. jdbcTemplate.update(“delete from users1 where id=10”);
6. }

在第二条删除语句中,users1表是不存在的,如果两次update语句是在两个事务中执行,则第一条能成功执行,并且数据库中该id的记录已经被删除,而第二条由于不存在该表不能正常删除。如果在同一事务中执行,由于第二条update出错,数据库中不能删除任何记录。

测试代码:

Java代码
1.@Test
2. public void testDelete()
3. {
4. userDAO.delete(5);
5. }

程序报错,同时id=5的记录没有被删除。如果我们把配置文件中关于事务配置的信息给注释掉,再次测试,程序同样报错,但是id=5的记录被成功删除掉,这说明这两条update语句是在两个不同的事务中运行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值