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 .} 
 
 
 
 
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于学习 Spring Boot 的项目学习路线,可以按照以下步骤进行: 1. 第一阶段:了解基础知识和概念。在此阶段,你可以开始学习 Spring Boot 的基础知识和核心概念,包括 Spring Framework、Spring Boot 的特点和优势等。可以参考中提供的学习路线,掌握基础知识和概念是深入学习 Spring Boot 的基础。 2. 第阶段:学习 Spring Boot Starter。Spring Boot Starter 是 Spring Boot 的一个重要特性,它提供了一种快速集成常用框架和库的方式。在此阶段,你可以学习如何使用已有的 Starter,例如 Spring Data JPA、Thymeleaf 等,来快速集成这些常用框架和库。这将有助于你在实际项目中更快地构建应用程序。可以参考中提供的学习内容,深入理解 Spring Boot Starter 的概念和作用。 3. 第三阶段:深入学习 Spring Boot 特性和功能。在这个阶段,你可以进一步深入学习 Spring Boot 的各种特性和功能,例如自动配置、Actuator、Spring Boot DevTools、Spring Security 等。通过学习和实践,你将能够更好地理解和应用这些功能,进一步提升你的开发能力。可以参考中提供的学习路线,逐步掌握 Spring Boot 的核心概念和功能。 通过以上学习路线,你可以系统地学习和掌握 Spring Boot 的核心概念和功能。随着实践项目的进行和不断学习,你将能够应对更复杂的需求和场景,深入理解和运用 Spring Boot 的各种特性和功能。希望这个学习路线对你的学习有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值