spring02 注解方式实现MVC、spring的继承、代理模式(静/动) :jdk动态代理,cglib动态代理

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_28139371/article/details/50447757


一、 注解:
     
    1、 基础回顾
           1、注解就是为了说明java中的某一个部分的作用(Type)
           2、注解都可以用于哪个部分是@Target注解起的作用
           3、注解可以标注在ElementType枚举类所指定的位置上(类、接口、注解类型、或枚举声明上)
           4、 
                 @Documented     //该注解是否出现在帮助文档中
                 @Retention(RetentionPolicy.RUNTIME) //该注解在java,class和运行时都起作用
                 @Target(ElementType.ANNOTATION_TYPE) //该注解只能用于注解上
                 public @interface Target {
                     ElementType[] value();
                 }
           5、用来解析注解的类成为注解解析器
           
        
    2、 依赖注入的注解解析器     
          1、 @Resource注解的使用规则:
                 1、在spring的配置文件中导入命名空间
                       xmlns:context="http://www.springframework.org/schema/context"
                       http://www.springframework.org/schema/context
                       http://www.springframework.org/schema/context/spring-context-2.5.xsd


                 2、引入依赖注入的注解解析器
                      <context:annotation-config></context:annotation-config>


                 3、在spring的配置文件中把bean引入进来


                 4、在一个类的属性上加
                          @Resource(name="student_annotation")
                          private Student student;
                          
                          注:从该注解本身
                               @Target({TYPE, FIELD, METHOD})
                               @Retention(RUNTIME)
                               public @interface Resource {
                                  String name() default "";
                               }
                               1、该注解可以用于属性上或者方法上,但是一般用户属性上 
                               2、该注解有一个属性name,默认值为""
                               3、atuowired和qualifier一起使用的作用与resource等同
                                       @Autowired
                                       @Qualifier("student_annotation")
                                       private Student student;


          
          2、 例子
               --------------------------------------------------------------------------------
                 类:
                    public class Student {
                        public void show(){
                          System.out.println("show student");
                        }
                    }
                    
                    public class Person {
                        private Long pid;
                        private String pname;
                       
                        // 只有引用类型使用注解,基本类型不适用
                        @Resource(name="student_annotation")
                        // 注: atuowired和qualifier一起使用的作用与resource等同
                        // @Autowired
                        // @Qualifier("student_annotation")
                        private Student student;
                        
                        public void showStudent(){
                          this.student.show();
                        }                      
                    }


                 配置文件:
                    <!-- 引入注解需要加注解解析器 -->
                    <context:annotation-config></context:annotation-config>         
                    <bean id="student_annotation" class="cn.itcast.annotation.di.Student"></bean>
                    <bean id="person_annotation" class="cn.itcast.annotation.di.Person"></bean>
                
                 测试:
                    @Test
                    public void test(){
                      ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
                      Person person = (Person) context.getBean("person_annotation");
                      person.showStudent();
                    }                         
               --------------------------------------------------------------------------------
           
           
          3、 分析加入注解后的spring整个过程:
                  1、当启动spring容器的时候,spring容器加载了配置文件
                  2、在spring配置文件中,只要遇到bean的配置,就会为该bean创建对象
                  3、在纳入spring容器的范围内查找所有的bean,看哪些bean的属性或者方法上加有@Resource
                  4、找到@Resource注解以后,判断该注解name的属性是否为""(name没有写)
                        如果没有写name属性,则会让属性的名称的值和spring中bean的id值做匹配,如果匹配成功则赋值
                                           如果匹配不成功,则会按照类型进行匹配,如果匹配不成功,则报错
                        如果有name属性,则会按照name属性的值和spring的bean中ID进行匹配,匹配成功,则赋值,不成功则
    
        
        
        
        
    3、 类扫描的注解 
          1、 @component注解的使用规则:
                   1、在spring的配置文件中导入命名空间
                         xmlns:context="http://www.springframework.org/schema/context"
                         http://www.springframework.org/schema/context
                         http://www.springframework.org/schema/context/spring-context-2.5.xsd


                   2、引入类扫描的注解解析器       
                         <context:component-scan base-package="cn.itcast.annotation.scan"></context:component-scan>
                         1、 component:指的就是一个类; 
                         2、 该注解解析器包含了两个功能:依赖注入和类扫描
                         3、 在base-package包及子包下查找所有的类  
                         4、如果一个类上加了@Component注解,就会进行如下的法则
                             如果其value属性的值为""
                                  @Component
                                  public class Person {}
                                    等价于
                                  <bean id="person" class="..Person">
                               如果其value属性的值不为""
                                  @Component("p")
                                  public class Person {}
                                    等价于
                                  <bean id="p" class="..Person">
                          5、按照@Resource的法则再次进行操作


        
           2、 例子
               --------------------------------------------------------------------------------
                类: 
                    @Component("b") 
                    public class Student {
                        public void show(){
                            System.out.println("scan student");
                        }
                    }
               
                    @Component("a")
                    public class Person {      
                        @Resource(name="b")
                        private Student student;
                        public void showStudent(){
                            System.out.println("show student scan");
                        }
                    }
               
                 配置文件:
                    <context:component-scan base-package="cn.itcast.annotation.scan"></context:component-scan>
                    
                 测试:
                    @Test
                    public void testPerson(){
                      ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");  
                      Person person = (Person) context.getBean("a");
                      person.showStudent();
                    }
               --------------------------------------------------------------------------------
        
   
    4、 XML配置实现依赖注入于注解实现依赖注入的区别
            1、xml书写麻烦,但是效率高
            2、注解书写简单,但是效率低,扫描companent一次,扫描resource又一次
            
            
            
    5、 类扫描的注解的细化
            1、 @component在MVC模式中可细化为:  @Controller  @Service  @Repository
            
            2、 用注解的方式实现MVC的案例
                  ---------------------------------------------------------------------------------------------
                  Action层:
                        @Controller("personAction")
                        public class PersonAction {                
                          
                            @Resource(name="personService")
                            private PersonService personService;
                            
                            public void savePerson(){
                              this.personService.savePerson();
                            }
                        }
                  
                  
                  Service层:
                        public interface PersonService {
                            public void savePerson();
                        }
                        
                  ServiceImpl层:
                        @Service("personService")
                        public class PersonServiceImpl implements PersonService {


                            @Resource(name="personDao")
                            private PersonDao personDao;
                            
                            public void savePerson() {
                              this.personDao.savePerson();
                            }


                        }
                  
                  
                  Dao层:
                        public interface PersonDao {
                          public void savePerson();
                        }
                        
                   
                  DaoImpl层:
                        @Repository("personDao")
                        public class PersonDaoImpl implements PersonDao {
                            public void savePerson() {
                              System.out.println("dao层操作数据库的代码");
                            }
                        }
                  
                  配置文件:
                        <context:component-scan base-package="cn.itcast.annotation.spring.mvc"></context:component-scan>
                        
                  测试:
                        public class MVCTest {
                            @Test
                            public void test(){
                              ApplicationContext context = new ClassPathXmlApplicationContext("
                                    cn/itcast/annotation/spring/mvc/applicationContext-spring-mvc-annotation-test.xml");             
                              PersonAction personAction = (PersonAction) context.getBean("personAction");
                              personAction.savePerson();
                            }
                        }
                  
                  ---------------------------------------------------------------------------------------------
            


        
        
二、 spring的继承


      1、如果一个类在spring配置文件中,但是不想让整个类创建对象,则用abstract="true"
      2、如果让一个子类拥有父类的属性,则parent="commonDao"


        例子:
           ------------------------------------------------------------------------------------------------------
           父类:
                public class CommonDao {
                    private String s;                    
                    public void saveEntity(){
                      System.out.println("save entity");
                    }                    
                    public void updateEntity(){
                      System.out.println("update entity");
                    }
                    public String getS() {
                      return s;
                    }
                    public void setS(String s) {
                      this.s = s;
                    }
                }
           
            子类:
                public class PersonDao extends CommonDao {
                    public void show(){
                      System.out.println("show personDao");
                    }
                }
            
            配置文件:
                <!-- abstract: 告诉spring容器,该类不能创建对象 -->
                <bean id="commonDao" class="cn.itcast.spring.extend.CommonDao" abstract="true">
                  <property name="s" value="aaa"></property>
                </bean>
                
                <!-- 子类使用父类的字段等,需要添加声明parent -->
                <bean id="personDao" class="cn.itcast.spring.extend.PersonDao" parent="commonDao"></bean>
           
            测试:
                public class ExtendTest {
                    @Test
                    public void test(){
                      ApplicationContext context = new ClassPathXmlApplicationContext("
                                cn/itcast/spring/extend/applicationContext-extend.xml");   
                      
                      // 注: CommonDao类在配置文件中声明为abstract 所以不能创建对象 
                  // CommonDao commonDao = (CommonDao) context.getBean("commonDao");
                  // commonDao.saveEntity();


                      PersonDao personDao = (PersonDao) context.getBean("personDao");
                      System.out.println(personDao.getS());
                      personDao.saveEntity();
                      personDao.updateEntity();
                      personDao.show();
                    }
                }
           
           ------------------------------------------------------------------------------------------------------
        
        
        
三、 代理模式


      1、 作用: 对于代码的增强
      
      2、 体系结构:  有一个目标借口, 有一个目标类和一个代理类都实现了该目标借口,
                    且代理类中存在目标类的引用


      3、 静态代理模式
            静态代理模式的缺点:
                1、如果一个系统中有100Dao,则创建100个代理对象
                2、如果一个dao中有很多方法需要事务,则代理对象的方法中重复代码还是很多
                3、由第一点和第二点可以得出:proxy的重用性不强
            
            解决途径: 动态代理
                
            例1:
            -------------------------------------------------------------------------------------------------------
                public interface PersonDao {
                    public void savePerson();
                }
                
                // 目标类
                public class PersonDaoImpl implements PersonDao {
                    public void savePerson() {
                      System.out.println("save person");
                    }
                }
              
                public class TransactionX {
                    public void beginTransaction(){
                      System.out.println("开启事务");
                    }
                    public void commit(){
                      System.out.println("提交事务");
                    }
                }
              
                public class PersonDaoProxy implements PersonDao {
                    private PersonDao personDao;
                    private TransactionX transactionx;
                    public PersonDaoProxy(PersonDao personDao,TransactionX transactionX) {
                      super();
                      this.personDao = personDao;
                      this.transactionx = transactionX;
                    }
                    public void savePerson() {
                      this.transactionx.beginTransaction();
                      this.personDao.savePerson();
                      this.transactionx.commit();
                    }
                }
                
                public class ProxyTest {
                    @Test
                    public void test(){
                        PersonDao target = new PersonDaoImpl();
                        TransactionX transactionX = new TransactionX();
                        PersonDao proxy = new PersonDaoProxy(target, transactionX);   
                        proxy.savePerson();
                    }
                }
              
            -------------------------------------------------------------------------------------------------------


            
            例2:
            -------------------------------------------------------------------------------------------------------
                public interface PersonDao {
                    public void savePerson();
                }
                
                public class PersonDaoImpl implements PersonDao {
                    public void savePerson() {
                      System.out.println("save person");
                    }
                }
                
                public class TransactionX {
                    public void beginTransaction(){
                      System.out.println("开启事务");
                    }
                    public void commit(){
                      System.out.println("提交事务");
                    }
                }
                
                
                public class PersonDaoProxy implements PersonDao {
                    private PersonDao personDao;
                    private TransactionX transactionx;
                    public PersonDaoProxy(PersonDao personDao,TransactionX transactionX) {
                      super();
                      this.personDao = personDao;
                      this.transactionx = transactionX;
                    }
                    public void savePerson() {
                      this.transactionx.beginTransaction();
                      this.personDao.savePerson();
                      this.transactionx.commit();
                    }
                }
                
                
                配置文件:
                    <bean id="personDao" class="cn.itcast.spring.proxy.PersonDaoImpl"></bean>
                    <bean id="transactionX" class="cn.itcast.spring.proxy.TransactionX"></bean>
                    <bean id="personDaoProxy" class="cn.itcast.spring.proxy.PersonDaoProxy">
                      <constructor-arg index="0" ref="personDao"></constructor-arg>
                      <constructor-arg index="1" ref="transactionX"></constructor-arg>
                    </bean>
                    
                测试:
                    public class ProxyTest {
                        @Test
                        public void test(){
                          ApplicationContext context = new ClassPathXmlApplicationContext("
                                  cn/itcast/spring/proxy/applicationContext-spring-proxy.xml");         
                          PersonDaoProxy personDaoProxy = (PersonDaoProxy) context.getBean("personDaoProxy");
                          personDaoProxy.deletePerson();
                        }
                    }
            
            -------------------------------------------------------------------------------------------------------
        
        
      4、 动态代理
            
            1、分类:
                  1、产生的代理对象和目标对象实现了共同的接口
                        jdk动态代理
                  2、代理对象是目标对象的子类
                        hibernate: Person person = session.load(Person.class,1L);  javassisit
                        spring:cglib动态代理
                          
            2、jdk动态代理详解
                  1、因为是用jdk的API做到的
                  2、代理对象是动态产生的
                  3、JDK动态代理的拦截器的写法步骤
                      引入目标类  
                      引入重复的代码类(如: 事务的开启关闭)
                      通过构造函数给目标类和事务赋值
                      填充invoke方法
                  4、标志: 生成的动态对象的debug为$proxy4
                  5、注意事项:
                        1、拦截器中invoke方法体的内容就是代理对象方法体的内容
                        2、当客户端执行代理对象.方法时,进入到了拦截器的invoke方法体
                        3、拦截器中invoke方法的method参数是在调用的时候赋值的
                  
                  例1 模拟jdk动态代理:
                   -------------------------------------------------------------------------------
                       public interface PersonDao {
                            public void savePerson();                       
                       }
                       
                       public class PersonDaoImpl implements PersonDao {
                            public void savePerson() {
                              System.out.println("save person");
                            }
                       }
                        
                       public class TransactionX {
                            public void beginTransaction(){
                                System.out.println("开启事务");
                            }                       
                            public void commit(){
                                System.out.println("提交事务");
                            }
                       } 
                                           
                       public class PersonInterceptor implements InvocationHandler {
                            private Object target;      // 目标类
                            private TransactionX transactionX;  // 事务                         
                            public PersonInterceptor(Object target, TransactionX transactionX) {
                                super();
                                this.target = target;
                                this.transactionX = transactionX;
                            }
                            public Object invoke(Object proxy, Method method, Object[] args)
                                throws Throwable {
                                this.transactionX.beginTransaction(); 
                                method.invoke(this.target, args); // 调用目标类的方法
                                this.transactionX.commit();
                                return null;
                            }
                        }
                       
                        public class ProxyTest {
                            @Test
                            public void test(){
                              Object target = new PersonDaoImpl();
                              TransactionX transactionX = new TransactionX();
                              PersonInterceptor personInterceptor = new PersonInterceptor(target, transactionX);
                              
                                // 生成动态的代理对象参数:  目标类的类加载器;  目标类实现的所有接口; 拦截器
                              PersonDao personDao = (PersonDao) Proxy.newProxyInstance(target.getClass().getClassLoader(), 
                                                        target.getClass().getInterfaces(), personInterceptor);         
                              personDao.deletePerson();                      
                            }
                        }
                     
                   -------------------------------------------------------------------------------
                 
                  例2 结合hibernate使用jdk动态代理(配置文件和工具类略)
                   -------------------------------------------------------------------------------
                        public class Person implements Serializable {
                            private Long pid;
                            private String pname;
                            private String psex;
                            // set/get属性
                        }
                        
                        public interface PersonDao {
                            public void savePerson(Person person);
                        }
                        
                        public class PersonDaoImpl extends HibernateUtil implements PersonDao {
                            public void savePerson(Person person) {
                                sessionFactory.getCurrentSession().save(person);
                            }
                        }
      
                        public class MyTransaction extends HibernateUtil{
                            private Transaction transaction;
                            public void beginTransaction(){
                              this.transaction = sessionFactory.getCurrentSession().beginTransaction();
                            }                           
                            public void commit(){
                              this.transaction.commit();
                            }                          
                        }
                        
                        public class PersonDaoInterceptor implements InvocationHandler {
                            private Object target;
                            private MyTransaction myTransaction;                          
                            public PersonDaoInterceptor(Object target, MyTransaction myTransaction) {
                                super();
                                this.target = target;
                                this.myTransaction = myTransaction;
                            }
                            public Object invoke(Object proxy, Method method, Object[] args)
                                throws Throwable {
                                this.myTransaction.beginTransaction();
                                method.invoke(this.target, args);
                                this.myTransaction.commit();
                                return null;
                            }
                        }
                        
                        public class ProxyTest {
                            @Test
                            public void test(){
                              Object target = new PersonDaoImpl();
                              MyTransaction myTransaction = new MyTransaction();
                              PersonDaoInterceptor personDaoInterceptor = new PersonDaoInterceptor(target, myTransaction);           
                              PersonDao personDao = (PersonDao) Proxy.newProxyInstance(target.getClass().getClassLoader(), 
                                                        target.getClass().getInterfaces(), personDaoInterceptor);            
                              Person person = new Person();
                              person.setPname("aaa");
                              person.setPsex("男");
                              personDao.savePerson(person);                              
                            }                         
                        }                                          
                   -------------------------------------------------------------------------------
          
            3、cglib动态代理
                  1、 所需jar包:   cglib.jar
                  2、 使用代码加强机制产生代理对象
                  3、 cglib产生的代理对象是目标对象的子类
                  
                  例子
                  ----------------------------------------------------------------------------------------------
                      public interface Interceptor {
                          public void interceptor();
                      }
                      
                      public class Logger implements Interceptor{
                          public void interceptor() {
                              System.out.println("启动日志");
                          }
                      }
                  
                      public class Privilege implements Interceptor{
                          public void interceptor() {
                              System.out.println("权限");
                          }                        
                      }
                  
                      public class Security implements Interceptor{
                          public void interceptor() {
                            System.out.println("安全性框架");
                          }
                      }
                  
                      public interface SalaryManager {
                          public void showSalary();
                      }
                      
                      public class SalaryManagerImpl implements SalaryManager{
                          public void showSalary() {
                              System.out.println("查看工资");
                          }
                      }




                      public class SalaryInterceptor implements MethodInterceptor{


                          private Object target;
                          private List<Interceptor> interceptors;
                          
                          public SalaryInterceptor(Object target, List<Interceptor> interceptors) {
                              super();
                              this.target = target;
                              this.interceptors = interceptors;
                          }
                          
                          // 使用代码加强机制产生代理对象
                          public Object createProxy(){
                              Enhancer enhancer = new Enhancer();
                              enhancer.setCallback(this);
                              enhancer.setSuperclass(this.target.getClass());
                              return enhancer.create();
                          }


                          // cglib的拦截器写法
                          public Object intercept(Object arg0, Method arg1, Object[] arg2,
                                      MethodProxy arg3) throws Throwable {
                              for (Interceptor interceptor : interceptors) {
                                interceptor.interceptor();
                              }
                              arg1.invoke(this.target, arg2);
                              return null;
                          }                  
                          
                          public class SalaryTest {
                              @Test
                              public void test(){
                                // 目标类
                                Object target = new SalaryManagerImpl();
                                Logger logger = new Logger();
                                Security security = new Security();
                                Privilege privilege = new Privilege();
                                List<Interceptor> interceptors = new ArrayList<Interceptor>();
                                interceptors.add(logger);
                                interceptors.add(security);
                                interceptors.add(privilege);
                                SalaryInterceptor salaryInterceptor = new SalaryInterceptor(target, interceptors);
                                
                                SalaryManagerImpl salaryManagerImpl = (SalaryManagerImpl) salaryInterceptor.createProxy();
                                salaryManagerImpl.showSalary();
                              }
                          }                         
                      }
                  ----------------------------------------------------------------------------------------------
        
        


        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
阅读更多

没有更多推荐了,返回首页