不错的Spring学习笔记(转)

本文内容纲要:不错的Spring学习笔记(转)

Spring学习笔记(1)----简单的实例

---------------------------------

首先需要准备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.<?xml version="1.0" encoding="UTF-8"?>

2.<beans xmlns="http://www.springframework.org/schema/beans"

3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

4. xmlns:context="http://www.springframework.org/schema/context"

5. xmlns:tx="http://www.springframework.org/schema/tx"

6. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

7. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd

8. http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

9.

10.</beans>

我们在配置文件中加入我们的bean信息

Xml代码

1.<bean id="userBean" class="com.szy.spring.implbean.UserBean" />

其中id作为标识符,class为类的包路径。

这样我们的配置文件就写好了,完整的配置文件呢如下。

Xml代码

1.<?xml version="1.0" encoding="UTF-8"?>

2.<beans xmlns="http://www.springframework.org/schema/beans"

3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

4. xmlns:context="http://www.springframework.org/schema/context"

5. xmlns:tx="http://www.springframework.org/schema/tx"

6. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

7. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd

8. http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

9.

10. <bean id="userBean" class="com.szy.spring.implbean.UserBean" />

11.</beans>

最后我们创建一个测试类测试:

Java代码

1.package com.szy.spring.test;

2.

3.import org.junit.Test;

4.import org.springframework.context.ApplicationContext;

5.import org.springframework.context.support.ClassPathXmlApplicationContext;

6.import com.szy.spring.interfacebean.PersonBean;

7.

8.

9.public class TestClass

10.{

11. @Test

12. public void testMethod() throws Exception

13. {

14. //读取配置文件

15. ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");

16. //获取UserBean的实例

17. PersonBean bean=(PersonBean)ctx.getBean("userBean");

18. //调用方法

19. bean.show();

20. }

21.}

运行,输入如下结果:

结果代码

1.Hello Kuka

Ok,我们的第一个Spring程序成功运行。

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

-------------------------------------------

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

使用类构造器直接实例化

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

使用实例工厂方法实例化

三种方式对应的配置如下

Xml代码

1.<?xml version="1.0" encoding="UTF-8"?>

2.<beans xmlns="http://www.springframework.org/schema/beans"

3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

4. xmlns:context="http://www.springframework.org/schema/context"

5. xmlns:tx="http://www.springframework.org/schema/tx"

6. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

7. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd

8. http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

9. <!-- 使用类构造器直接实例化 -->

10. <bean id="userBean1" class="com.szy.spring.implbean.UserBean" />

11. <!-- 使用静态工厂的方法实例化 -->

12. <bean id="userBean2" class="com.szy.spring.factory.BeanFactory" factory-method="UserBeanService" />

13. <!-- 使用实例工厂方法实例化 -->

14. <bean id="factory" class="com.szy.spring.factory.BeanFactory" />

15. <bean id="userBean3" factory-bean="factory" factory-method="getUserBeanService" />

16.</beans>

其中BeanFactory类的代码如下

Java代码

1.package com.szy.spring.factory;

2.

3.import com.szy.spring.implbean.UserBean;

4.import com.szy.spring.interfacebean.PersonBean;

5.

6.public class BeanFactory

7.{

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

9. public static PersonBean UserBeanService()

10. {

11. return new UserBean();

12. }

13.

14. public PersonBean getUserBeanService()

15. {

16. return new UserBean();

17. }

18.}

在这三种方式中我们最常用的还是第一种。

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

--------------------------------------------------

Xml代码

1.<?xml version="1.0" encoding="UTF-8"?>

2.<beans xmlns="http://www.springframework.org/schema/beans"

3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

4. xmlns:context="http://www.springframework.org/schema/context"

5. xmlns:tx="http://www.springframework.org/schema/tx"

6. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

7. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd

8. http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

9. <bean id="userBean" class="com.szy.spring.implbean.UserBean" />

10.</beans>

Spring的配置文件中记录了类的包路径,因此我们首先是要读入配置文件。在配置文件中Bean有id和class两个属性,我们首先定义一个Bean类,包含这两个属性:

Java代码

1.package com.szy.spring.implbean;

2.

3.public class Bean

4.{

5. private String id;

6. private String className;

7. public String getId()

8. {

9. return id;

10. }

11. public void setId(String id)

12. {

13. this.id = id;

14. }

15. public String getClassName()

16. {

17. return className;

18. }

19. public void setClassName(String className)

20. {

21. this.className = className;

22. }

23.

24.}

25.

由于配置文件是xml文件,在这里使用Jdom包操作xml文件,读入配置文件中的Bean信息。

Java代码

1./**

2. * 读取xml配置文件

3. * @param fileName 配置文件名

4. */

5. private void readXML(String fileName)

6. {

7. // 寻找配置文件

8. URL xmlPath = this.getClass().getClassLoader().getResource(fileName);

9. Document doc = null;

10. Element root = null;

11. try

12. {

13. SAXBuilder sb = new SAXBuilder(false);

14. doc = sb.build(new FileInputStream(new File(xmlPath.toURI())));

15. // 设置命名空间

16. Namespace xhtml = Namespace.getNamespace("xhtml",

17. "http://www.springframework.org/schema/beans");

18. root = doc.getRootElement(); // 获取根元素

19. List<Element> list = root.getChildren("bean", xhtml); //获取全部bean节点

20. for (Element element : list)// 遍历节点,取得每个节点的属性

21. {

22. String id = element.getAttributeValue("id");

23. String className = element.getAttributeValue("class");

24. Bean bean = new Bean();

25. bean.setId(id);

26. bean.setClassName(className);

27. beanList.add(bean);

28. }

29. } catch (Exception e)

30. {

31. e.printStackTrace();

32. }

33.

34. }

其中beanList是一个List对象,因为在配置文件中存在很多Bean。

得到了所有的Bean对象后,下面就实例化每个Bean对象,结果存放在Map对象中。

Java代码

1./**

2. * bean的实例化

3. */

4. private void instanceBeans()

5. {

6. for (Bean bean : beanList)

7. {

8. try

9. {

10. if (bean.getClassName() != null && !"".equals(bean.getClassName().trim()))

11. beanObject.put(bean.getId(), Class.forName(bean.getClassName()).newInstance());

12. } catch (Exception e)

13. {

14. e.printStackTrace();

15. }

16. }

17.

18. }

其中beanObject为Map对象。

最后再加入一个方法,方便外部能获取Map中的对象

Java代码

1./**

2. * 获取bean实例

3. * @param beanName 配置文件中bean的Id

4. * @return

5. */

6. public Object getBean(String beanName)

7. {

8. return this.beanObject.get(beanName);

9. }

完整的MyClassPathXMLApplicationContext见附件中的代码。

下面测试MyClassPathXMLApplicationContext类。

Java代码

1.@Test

2. public void testMethod() throws Exception

3. {

4. //读取配置文件

5. MyClassPathXMLApplicationContext ctx=new MyClassPathXMLApplicationContext("applicationContext.xml");

6. //获取UserBean的实例

7. PersonBean bean=(PersonBean)ctx.getBean("userBean");

8. //调用方法

9. bean.show();

10. }

输出结果

结果代码

1.Hello Kuka

成功。

上面仅是简单的演示了Spring管理Bean的原理,但是在实际操作中还需要考虑很对其它因素。

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

---------------------------------------

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

Xml代码

1.<bean id="userBean" class="com.szy.spring.implbean.UserBean" lazy-init="true" />

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

Xml代码

1.<beans default-lazy-init="true"....>

此外,如果我们还想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.<bean id="userBean" class="com.szy.spring.implbean.UserBean" scope="prototype" />

在运行测试代码,输出结果为: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.<?xml version="1.0" encoding="UTF-8"?>

2.<beans xmlns="http://www.springframework.org/schema/beans"

3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

4. xmlns:context="http://www.springframework.org/schema/context"

5. xmlns:tx="http://www.springframework.org/schema/tx"

6. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

7. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd

8. http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

9. <bean id="mySqlDAO" class="com.szy.spring.dao.UserDAO4MySqlImpl"/>

10. <bean id="oracleDAO" class="com.szy.spring.dao.UserDAO4OracleImpl"/>

11. <bean id="userService" class="com.szy.spring.service.UserServiceImpl">

12. <!--构造方法注入

13. <property name="userDAO" ref="mySqlDAO"></property>

14. -->

15. <property name="userDAO" ref="oracleDAO"></property>

16. </bean>

17.</beans>

下面我们测试

Java代码

1.ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");

2. UserService service=(UserService)ctx.getBean("userService");

3. service.show();

输入内容为

输出代码

1.OracleDAO Implement

如果我们想实用Mysql数据库呢?

此时我们只要修改配置文件即可,而不需要修改Java文件。

Xml代码

1.<property name="userDAO" ref="mySqlDAO"></property>

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

---------------------------------------------------

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

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

Xml代码

1.<?xml version="1.0" encoding="UTF-8"?>

2.<beans xmlns="http://www.springframework.org/schema/beans"

3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

4. xmlns:context="http://www.springframework.org/schema/context"

5. xmlns:tx="http://www.springframework.org/schema/tx"

6. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

7. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd

8. http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

9. <bean id="mySqlDAO" class="com.szy.spring.dao.UserDAO4MySqlImpl"/>

10. <bean id="oracleDAO" class="com.szy.spring.dao.UserDAO4OracleImpl"/>

11. <bean id="userService" class="com.szy.spring.service.UserServiceImpl">

12. <!--构造方法注入

13. <property name="userDAO" ref="mySqlDAO"></property>

14. -->

15. <property name="userDAO" ref="oracleDAO"></property>

16. </bean>

17.</beans>

根据配置文件信息,我们首先需要建立一个Bean类,用来保存bean节点的信息:

Java代码

1.package com.szy.spring.bean;

2.

3.import java.util.List;

4.

5.public class Bean

6.{

7. private String id;

8. private String className;

9. private List<Property> propertyList;

10. public Bean(String id, String className, List<Property> propertyList)

11. {

12. super();

13. this.id = id;

14. this.className = className;

15. this.propertyList = propertyList;

16. }

17. public String getId()

18. {

19. return id;

20. }

21. public void setId(String id)

22. {

23. this.id = id;

24. }

25. public String getClassName()

26. {

27. return className;

28. }

29. public void setClassName(String className)

30. {

31. this.className = className;

32. }

33. public List<Property> getPropertyList()

34. {

35. return propertyList;

36. }

37. public void setPropertyList(List<Property> propertyList)

38. {

39. this.propertyList = propertyList;

40. }

41.}

此外,由于bean下存在property信息,因此我们还需要建立property类

Java代码

1.package com.szy.spring.bean;

2.

3.public class Property

4.{

5. private String name;

6. private String ref;

7.

8. public Property(String name, String ref)

9. {

10. super();

11. this.name = name;

12. this.ref = ref;

13. }

14. public String getName()

15. {

16. return name;

17. }

18. public void setName(String name)

19. {

20. this.name = name;

21. }

22. public String getRef()

23. {

24. return ref;

25. }

26. public void setRef(String ref)

27. {

28. this.ref = ref;

29. }

30.

31.}

在Spring学习笔记(3)中,我们在读取xml文件时bean节点下面是不存在property节点的,因此在这里我们需要修改readXML()方法:

Java代码

1./**

2. * 读取xml配置文件

3. * @param fileName 配置文件名

4. */

5. private void readXML(String fileName)

6. {

7. // 寻找配置文件

8. URL xmlPath = this.getClass().getClassLoader().getResource(fileName);

9. Document doc = null;

10. Element root = null;

11. try

12. {

13. SAXBuilder sb = new SAXBuilder(false);

14. doc = sb.build(new FileInputStream(new File(xmlPath.toURI())));

15. // 设置命名空间

16. Namespace xhtml = Namespace.getNamespace("xhtml",

17. "http://www.springframework.org/schema/beans");

18. root = doc.getRootElement(); // 获取根元素

19. List<Element> bList = root.getChildren("bean", xhtml); //获取全部bean节点

20. for (Element beanElement : bList)// 遍历节点,取得每个节点的属性

21. {

22. String id = beanElement.getAttributeValue("id");

23. String className = beanElement.getAttributeValue("class");

24. //获得每个bean下面的属性

25. List<Element> pList = beanElement

26. .getChildren("property", xhtml);

27. List<Property> propertyList = new ArrayList<Property>(); //存储属性信息

28. if (pList.size() > 0) //如果存在属性

29. {

30. for (Element propertyElement : pList) //遍历属性节点

31. {

32. String name = propertyElement.getAttributeValue("name");

33. String ref = propertyElement.getAttributeValue("ref");

34. Property property = new Property(name, ref);

35. propertyList.add(property); //保存属性节点

36. }

37. }

38. Bean bean = new Bean(id, className, propertyList);

39. beanList.add(bean);

40. }

41.

42. } catch (Exception e)

43. {

44. e.printStackTrace();

45. }

46. }

读取完配置文件后我们还是需要对bean进行实例化的,这方法和Spring学习笔记(3)中的instanceBeans()方法一样。下面就是我们需要给bean属性进行注入,实现方法如下:

Java代码

1./**

2. * 为bean对象的属性注入值

3. */

4. public void injectObject()

5. {

6. for (Bean bean : beanList)

7. {

8. Object object = beanObject.get(bean.getId()); //获取bean的实例

9. if (object != null)

10. {

11. try

12. {

13. PropertyDescriptor[] ps = Introspector.getBeanInfo(

14. object.getClass()).getPropertyDescriptors(); //取得bean的属性描述

15. for (Property property : bean.getPropertyList()) //获取bean节点的属性

16. {

17. for (PropertyDescriptor properdesc : ps)

18. {

19. if (property.getName().equals(properdesc.getName()))

20. {

21. Method setter = properdesc.getWriteMethod();//获取属性的setter方法 ,private

22. if (setter != null)

23. {

24. Object value = beanObject.get(property.getRef()); //取得值

25. setter.setAccessible(true); //设置为允许访问

26. setter.invoke(object, value);//把引用对象注入到属性

27. }

28. break;

29. }

30. }

31. }

32. } catch (Exception e)

33. {

34. e.printStackTrace();

35. }

36. }

37. }

我们进行测试:

Java代码

1.MyClassPathXMLApplicationContext ctx=new MyClassPathXMLApplicationContext("applicationContext.xml");

2. UserService service=(UserService)ctx.getBean("userService");

3. service.show();

运行输出

结果代码

1.OracleDAO Implement

上面仅是简单的演示了Spring依赖注入的原理,但是Spring学习笔记(7)----装配各种集合类型的属性在实际操作中还需要考虑很对其它因素,在此就不进行讨论了。

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

---------------------------------------------

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

1.Set类型

Java代码

1.private Set<String> sets=new HashSet<String>();

2.//我们需要给它添加set方法

3.public Set<String> getSets()

4. {

5. return sets;

6. }

7. public void setSets(Set<String> sets)

8. {

9. this.sets = sets;

10. }

11.public Set<String> showSet()

12. {

13. return sets;

14. }

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

Xml代码

1.<bean id="userService" class="com.szy.spring.service.UserServiceImpl">

2. <property name="sets">

3. <set>

4. <value>Set1</value>

5. <value>Set2</value>

6. <value>Set3</value>

7. </set>

8. </property>

9.

10.</bean>

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

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

2.List类型

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

Java代码

1.private List<String> lists=new ArrayList<String>();

2.public List<String> getLists()

3. {

4. return lists;

5. }

6. public void setLists(List<String> lists)

7. {

8. this.lists = lists;

9. }

10.public List<String> showList()

11. {

12. return lists;

13. }

配置文件修改如下

Xml代码

1.<bean id="userService" class="com.szy.spring.service.UserServiceImpl">

2.<property name="lists">

3. <list>

4. <value>List1</value>

5. <value>List2</value>

6. <value>List3</value>

7. </list>

8. </property>

9. </bean>

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.<bean id="userService" class="com.szy.spring.service.UserServiceImpl">

2.<property name="properties">

3. <props>

4. <prop key="key1">Properties1</prop>

5. <prop key="key2">Properties2</prop>

6. <prop key="key3">Properties3</prop>

7. </props>

8. </property>

9. </bean>

10.

4.Map类型

Java代码

1.private Map<String, String> maps=new HashMap<String, String>();

2.public List<String> getLists()

3. {

4. return lists;

5. }

6. public void setLists(List<String> lists)

7. {

8. this.lists = lists;

9. }

10.public Map<String, String> showMaps()

11. {

12. return maps;

13. }

配置文件做相应的配置

Xml代码

1.<bean id="userService" class="com.szy.spring.service.UserServiceImpl">

2.lt;property name="maps">

3. <map>

4. <entry key="key1" value="Map1"></entry>

5. <entry key="key2" value="Map2"></entry>

6. <entry key="key3" value="Map3"></entry>

7. </map>

8. </property>

9.</bean>

这样就完成了对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.<bean id="personDao" class="com.szy.spring.dao.PersonDaoBean"/>

2. <!-- 使用属性Setter方法注入配置 -->

3. <bean id="userService1" class="com.szy.spring.service.UserServiceImplBySetter">

4. <property name="personDao" ref="personDao"></property>

5. </bean>

使用构造器注入

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

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.<bean id="personDao" class="com.szy.spring.dao.PersonDaoBean"/>

2. <!-- 使用构造器参数方法注入配置 -->

3. <bean id="userService2" class="com.szy.spring.service.UserServiceImplConstructor">

4. <constructor-arg index="0" type="com.szy.spring.dao.PersonDao" ref="personDao"/>

5. <constructor-arg index="1" value="Kuka"/>

6. </bean>

注意: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.<?xml version="1.0" encoding="UTF-8"?>

2.<beans xmlns="http://www.springframework.org/schema/beans"

3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

4. xmlns:context="http://www.springframework.org/schema/context"

5. xmlns:tx="http://www.springframework.org/schema/tx"

6. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

7. http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd

8. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">

9. <context:annotation-config/>

10. <bean id="personDao" class="com.szy.spring.dao.PersonDaoBean"/>

11. <bean id="userService" class="com.szy.spring.service.UserServiceImplByAnnotation4Autowired">

12. </bean>

13.</beans>

注意添加这句配置信息

<context:annotation-config/>

第二中方式就是使用spring提供的注解方式

org.springframework.beans.factory.annotation.Autowired;

注入使用时需要导入spring目录lib\j2ee\common-annotations.jar这个包

使用方法如下:

Java代码

1.package com.szy.spring.service;

2.

3.import org.springframework.beans.factory.annotation.Autowired;

4.import org.springframework.beans.factory.annotation.Qualifier;

5.

6.import com.szy.spring.dao.PersonDao;

7.

8.public class UserServiceImplByAnnotation4Autowired implements UserService

9.{

10. //@Autowired默认使用类型进行装配,

11. @Autowired private PersonDao personDao;

12.// 如果使用按名称进行装配,则需要如下

13.// @Autowired @Qualifier("personDao")private PersonDao personDao;

14. public void show()

15. {

16. personDao.show();

17. }

18.

19.}

配置文件和上面一样。

在使用时建议使用@Resource,因为@Resource不依赖于spring框架。

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.<?xml version="1.0" encoding="UTF-8"?>

2.<beans xmlns="http://www.springframework.org/schema/beans"

3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

4. xmlns:context="http://www.springframework.org/schema/context"

5. xmlns:tx="http://www.springframework.org/schema/tx"

6. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

7. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd

8. http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

9. <context:component-scan base-package="com.szy.spring"></context:component-scan>

10.</beans>

其中base-package为需要扫描的包(包括子包)

@Service用于标注业务层的组件,@Controller用于标注控制层组件(如struts中的action),@Repository用于标注数据访问组件,即DAO组件,而@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。但是在目前的spring版本中,这几个注解的作用是一样的,但是在以后可能会进行区分。

下面把先前的例子修改一下:

首先是PersonDaoBean类,修改如下

Java代码

1.package com.szy.spring.dao;

2.

3.import org.springframework.stereotype.Repository;

4.

5.@Repository

6.//告诉spring这个类要交给spring管理,

7.public class PersonDaoBean implements PersonDao

8.{

9. public void show()

10. {

11. System.out.println("执行PersonDaoBean中的add()方法");

12. }

13.}

然后是UserServiceImpl类

Java代码

1.package com.szy.spring.service;

2.

3.import org.springframework.stereotype.Service;

4.

5.import com.szy.spring.dao.PersonDao;

6.@Service

7.//把这个类交给spring管理,作为服务了。

8.public class UserServiceImpl implements UserService

9.{

10. private PersonDao personDaoBean;

11.

12. public void show()

13. {

14. personDaoBean.show();

15. }

16.

17. public void setPersonDaoBean(PersonDao personDaoBean)

18. {

19. this.personDaoBean = personDaoBean;

20. }

21.

22. public PersonDao getPersonDaoBean()

23. {

24. return personDaoBean;

25. }

26.}

下面我们进行测试,原来的测试代码是userServiceImpl

Java代码

1.ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");

2. UserService service=(UserService)ctx.getBean("userService");

3. service.show();

其中userService是我们在配置文件中配置的bean的id。但是如今我们并没有id这个属性,在spring2.5中,默认的id是类的名称,但是开后是小写,也就是userServiceImpl,因此测试代码应修改如下:

Java代码

1.AbstractApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");

2. UserService service=(UserService)ctx.getBean("userServiceImpl");

3. System.out.println(service);

如果我们想自己命名的话,则只需在注解后加上括号,里面写入你希望的名字,如

@Service("userService")。

在spring中默认的是之生成一个bean实例,如果我们想每次调用都产生一个实例,则标注需如下配置

@Service @Scope("prototype")

在xml中我们还可以配置初始化方法和销毁方法,使用标注后只需如下标注

Java代码

1.@PostConstruct

2. public void init()

3. {

4. System.out.println("初始化");

5. }

6. @PreDestroy

7. public void destory()

8. {

9. System.out.println("销毁");

10. }

使用注解后,我们的xml文件变得十分简单,因此建议Spring学习笔记(10)----公共属性的注入配置大家在以后的开发中使用注解。

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.<?xml version="1.0" encoding="UTF-8"?>

2.<beans xmlns="http://www.springframework.org/schema/beans"

3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

4. xmlns:context="http://www.springframework.org/schema/context"

5. xmlns:tx="http://www.springframework.org/schema/tx"

6. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

7. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd

8. http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

9. <bean id="bean1" class="com.szy.spring.bean.Bean1">

10. <property name="bean2" ref="bean2"/>

11. <property name="bean3">

12. <ref bean="bean3"/>

13. </property>

14. <property name="bean4" ref="bean4"/>

15. </bean>

16.

17. <bean id="bean2" class="com.szy.spring.bean.Bean2">

18. <property name="id" value="100"/>

19. <property name="name">

20. <value>kuka</value>

21. </property>

22. <property name="password" value="123"/>

23. </bean>

24.

25. <bean id="bean3" class="com.szy.spring.bean.Bean3">

26. <property name="id" value="100"/>

27. <property name="name" value="kuka"/>

28. </bean>

29.

30. <bean id="bean4" class="com.szy.spring.bean.Bean4">

31. <property name="age" value="22"/>

32. </bean>

33.</beans>

我们进行测试:

Java代码

1.@Test

2. public void testMethod() throws Exception

3. {

4. ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");

5. Bean1 bean1 = (Bean1)ctx.getBean("bean1");

6.

7. System.out.println("bean1.bean2.id=" + bean1.getBean2().getId());

8. System.out.println("bean1.bean2.name=" + bean1.getBean2().getName());

9. System.out.println("bean1.bean2.password=" + bean1.getBean2().getPassword());

10. System.out.println("bean1.bean3.id=" + bean1.getBean3().getId());

11. System.out.println("bean1.bean3.name=" + bean1.getBean3().getName());

12. System.out.println("bean1.bean4.age=" + bean1.getBean4().getAge());

13. }

正常输出我们所预期的信息,但是我们观察发现bean2和bean3的部分属性的配置信息是相同的,这仅是两个bean,如果是多个bean的话我们要修改就好修改多处,因此我们可以把这些公共的部分提出出来,进行抽象。这个在Spring中是支持的。我们在建立一个配置文件,命名为:applicationCommon.xml,其内容如下配置

Xml代码

1.<?xml version="1.0" encoding="UTF-8"?>

2.<beans xmlns="http://www.springframework.org/schema/beans"

3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

4. xmlns:context="http://www.springframework.org/schema/context"

5. xmlns:tx="http://www.springframework.org/schema/tx"

6. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

7. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd

8. http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

9. <bean id="beanAbstract" abstract="true">

10. <property name="id" value="100"/>

11. <property name="name" value="kuka"/>

12. </bean>

13.

14. <bean id="bean2" class="com.szy.spring.bean.Bean2" parent="beanAbstract">

15. <property name="password" value="123"/>

16. </bean>

17.

18. <bean id="bean3" class="com.szy.spring.bean.Bean3" parent="beanAbstract"/>

19.

20.</beans>

beanAbstract就是我们抽象出来的,设置abstract="true"属性后就不需要指定class属性。

我们把原来配置文件里的关于bean2和bean3节点注释掉。

下面进行测试,在这里要注意由于我们使用了两个配置文件,因此我们在读取是要写两个配置文件名。我们查看ClassPathXmlApplicationContext源文件发现其有个构造函数参数是string数组,因此我们可以把这个配置文件名放在数组里面。此外我们还有另外一种实现方法,两个配置文件一个叫applicationContext.xml,另一个applicationCommon.xml,公共部分是applicationC*.xml,下面我们就可以这样进行测试:

Java代码

1.@Test

2. public void testMethod() throws Exception

3. {

4. ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationC*.xml");

5. Bean1 bean1 = (Bean1)ctx.getBean("bean1");

6.

7. System.out.println("bean1.bean2.id=" + bean1.getBean2().getId());

8. System.out.println("bean1.bean2.name=" + bean1.getBean2().getName());

9. System.out.println("bean1.bean2.password=" + bean1.getBean2().getPassword());

10. System.out.println("bean1.bean3.id=" + bean1.getBean3().getId());

11. System.out.println("bean1.bean3.name=" + bean1.getBean3().getName());

12. System.out.println("bean1.bean4.age=" + bean1.getBean4().getAge());

13. }

如果我们bean2的name属性的值不是kuka,那么我们只需在applicationCommon.xml文件的bean2节点下再添加property属性即可

Xml代码

1.<property name="name" value="coolszy"/>

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.<bean id="bean" class="com.szy.spring.bean.Bean">

2. <property name="date" value="2009-11-21"/>

3. </bean>

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

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.<?xml version="1.0" encoding="UTF-8"?>

2.<beans xmlns="http://www.springframework.org/schema/beans"

3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

4. xmlns:context="http://www.springframework.org/schema/context"

5. xmlns:tx="http://www.springframework.org/schema/tx"

6. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

7. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd

8. http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

9. <bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer">

10. <!-- 把值注入到CustomEditorConfigurer的 Map类型的customEditors属性-->

11. <property name="customEditors">

12. <map>

13. <entry key="java.util.Date">

14. <!-- 内部bean只供自己使用 -->

15. <bean class="com.szy.spring.util.DatePropertyEditor"/>

16. </entry>

17. </map>

18. </property>

19. </bean>

20.

21.</beans>

下面我们修改下测试代码已读取所有的配置文件

Java代码

1.ApplicationContext ctx=new ClassPathXmlApplicationContext("application*.xml");

2. Bean bean = (Bean)ctx.getBean("bean");

3. System.out.println(bean.getDate());

最后测试,成功输出时间。

刚才我们在配置文件中时间的格式是2009-11-21,如果我们修改成2009/11/21呢?

运行报错:Unparseable date: "2009/11/21"

这时我们需要修改属性编辑器类文件的格式了,很麻烦。既然spring支持注入,那么我们为什么不对格式进行注入呢?

修改属性编辑器类:

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. private String format;

11. @Override

12. public void setAsText(String text) throws IllegalArgumentException

13. {

14.

15. SimpleDateFormat sdf=new SimpleDateFormat(format);

16. try

17. {

18. Date date=sdf.parse(text);

19. this.setValue(date); //把转换后的值传过去

20. } catch (Exception e)

21. {

22. e.printStackTrace();

23. }

24. }

25. public String getFormat()

26. {

27. return format;

28. }

29. public void setFormat(String format)

30. {

31. this.format = format;

32. }

33.}

同时给该类对应的bean添加属性节点

Xml代码

1.<bean class="com.szy.spring.util.DatePropertyEditor">

2. <property name="format" value="yyyy/MM/dd"></property>

3. </bean>

下次只要我们修改配置文件即可,灵活性很大。

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.<aop:aspectj-autoproxy/>

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

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.<bean id="interceptor" class="com.szy.spring.Interceptor"/>

下面我们进行测试

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.<bean id="aspetbean" class="com.szy.spring.Interceptor"/>

2. <aop:config>

3. <aop:aspect id="aspet" ref="aspetbean">

4. <aop:pointcut id="cut" expression="execution (* com.szy.spring.UserManagerImpl.*(..))"/>

5. <aop:before pointcut-ref="cut" method="doBefore"/>

6. <aop:after-returning pointcut-ref="cut" method="doAfterReturning"/>

7. <aop:after pointcut-ref="cut" method="doAfter"/>

8. <aop:after-throwing pointcut-ref="cut" method="doAfterThrowing"/>

9. <aop:around pointcut-ref="cut" method="doAround"/>

10. </aop:aspect>

11. </aop:config>

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

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

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

--------------------------------------------------

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

*配置数据源,例如:

Xml代码

1.<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">

2. <property name="driverClassName" value="com.mysql.jdbc.Driver"/>

3. <property name="url" value="jdbc:mysql://localhost:3306/test"/>

4. <property name="username" value="root"/>

5. <property name="password" value="123456"/>

6. <!-- 连接池启动时的初始值 -->

7. <property name="initialSize" value="1"/>

8. <!-- 连接池的最大值 -->

9. <property name="maxActive" value="100"/>

10. <!-- 最大空闲值.当经过一个高峰时间后,连接池可以慢慢将已经用不到的连接慢慢释放一部分,一直减少到maxIdle为止 -->

11. <property name="maxIdle" value="2"/>

12. <!-- 最小空闲值.当空闲的连接数少于阀值时,连接池就会预申请去一些连接,以免洪峰来时来不及申请 -->

13. <property name="minIdle" value="1"/>

14. </bean>

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

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

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

Xml代码

1.<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

2. <!-- 指定数据源 -->

3. <property name="dataSource" ref="dataSource"/>

4. </bean>

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

Xml代码

1.<tx:annotation-driven transaction-manager="txManager"/>

这样我们的配置文件配置完成,下面我们在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<User> 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<User> 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.<bean id="userDAO" class="com.szy.spring.dao.impl.UserDAOImpl"/>

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

Java代码

1.private DataSource dataSource;

2.

3. public void setDataSource(DataSource dataSource)

4. {

5. this.dataSource = dataSource;

6. }

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

Xml代码

1.<bean id="userDAO" class="com.szy.spring.service.impl.UserDAOImpl">

2. <property name="dataSource" ref="dataSource"/>

3. </bean>

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

在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<User> getAllUsers()

33. {

34. return (List<User>)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.<context:property-placeholder location="classpath:jdbc.properties"/>

2. <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">

3. <property name="driverClassName" value="${driverClassName}"/>

4. <property name="url" value="${url}"/>

5. <property name="username" value="${username}"/>

6. <property name="password" value="${password}"/>

7. <property name="initialSize" value="${initialSize}"/>

8. <property name="maxActive" value="${maxActive}"/>

9. <property name="maxIdle" value="${maxIdle}"/>

10. <property name="minIdle" value="${minIdle}"/>

11. </bean>

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

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

-------------------------------------------------------

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

Xml代码

1.<aop:config>

2. <aop:pointcut id="transactionPointcut" expression="execution(* com.szy.spring.dao.impl..*.*(..))"/>

3. <aop:advisor advice-ref="txAdvice" pointcut-ref="transactionPointcut"/>

4. </aop:config>

5. <tx:advice id="txAdvice" transaction-manager="txManager">

6. <tx:attributes>

7. <!-- 如果连接的方法是以get开头的方法,则不使用事务 -->

8. <tx:method name="get*" read-only="true" propagation="NOT_SUPPORTED"/>

9. <tx:method name="*"/>

10. </tx:attributes>

11. </tx:advice>

这样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语句是在两个不同的事务中运行。

PS:在平时开发中,Spring团队建议使用注解的方式进行配置,这样配置文件显得精简,同时也会做到精确控制。

  

本文内容总结:不错的Spring学习笔记(转)

原文链接:https://www.cnblogs.com/cyjch/archive/2012/02/06/2340415.html

以上是 不错的Spring学习笔记(转) 的全部内容, 来源链接: utcz.com/z/296148.html

回到顶部