• Spring核心知识整理(一)


    Spring核心技术

    DI:依赖注入
    IOC:控制反转
    AOP:面向切面编程   -- 思想必须掌握
    

    1.Spring配置文件和通过工厂对象创键实例对象

    命名无限制,约定有:spring-context.xml,applicationContext.xml,beans.xml
    
    文件结构

    bean标签属性讲解

    id

    Spring-Bean唯一标识

    class

    Spring-Bean全限定类名

    init-method

    指定Spring-Bean初始化函数 - 在 class的类里面定义的函数

    destroy-method

    指定Spring-Bean销毁函数

    scope

    指定Spring-Bean生命周期 Spring-Bean的生命周期有以下6种:

    • singleton

      单例

    • prototype

      多例

    • request

      请求域

    • session

      会话域

    • application

      上下文域

    • websocket

      会话建立连接时创建,断开连接时销毁

    spring-context.xml
    <!--配置实例(id:唯一标识, class="需要被创建对象的完全类名"-->
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           https://www.springframework.org/schema/beans/spring-beans.xsd">
        <bean id="mc" class="MyClass"/>
    </beans>      
    
    <!--xmlns:xml namespaces,命名空间,为了避免Spring的beans标签和其他文件中的beans标签重名导致冲突-->
           <!--xmlns:xsi : 该文件使用的其他命名空间,名称为xsi,在使用其中的标签时要加入xsi:的前缀.
           xmlns冒号后面的命名空间不是固定的,可以变更。xmlns语法为:xmlns:namespace-prefix="namespaceURL"-->
           <!--xsi:schemaLocation:属性的值由一个URL引用对组成,两个URL之间以空白符分隔。第一个URL时名称空间的名字
           ,第二个URL给出模式文档的位置,模式处理器将从这个位置读取模式文档,该模式文档的目标名称空间必须与第一个URL相匹配-->
    <!-- 注意:beans标签里面不能添加中文注释,否则报错 -->
    <!-- 报错如下:
    org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line 7 in XML document from class path resource [spring-context.xml] is invalid; nested exception is org.xml.sax.SAXParseException; lineNumber: 7; columnNumber: 13; 2 字节的 UTF-8 序列的字节 2 无效。
    -->
    
    pom.xml
    <!--Spring-context:spring工厂 常用依赖-->
    <dependency>
    	<groupId>org.springframework</groupId>
    	<artifactId>spring-context</artifactId>
    	<version>5.3.15</version>
    </dependency>
    
    Myclass
    public class MyClass {
        public void show(){
            System.out.println("HelloWorld");
        }
    }
    
    TestFactory
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class TestFactory {
        /**
         * 程序中的对象都交由Spring的ApplicationContext工厂进行创建
         */
        public static void main(String[] args) {
            // springcontext是spring工厂
            // 获取工厂对象
            ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-context.xml");
            // 通过id创键bean对象
            MyClass m = (MyClass) ctx.getBean("mc");
            // 调用m对象的方法
            m.show();
        }
    }
    

    2.IoC(Inversion of Control) 控制反转 -- 解决接口和实现类之间的强耦合关系

    Inversion of Control: 控制反转

    反转了依赖关系的满足方式,由之前的自己创建依赖对象,变为由工厂推送。(变主动为被动,即反转)

    解决了具有依赖关系的组件之间的强耦合,使得项目形态更加稳健

    在项目中表现:在接口实现类中只定义接口对象,不创建,创建和赋值交给Spring工厂

    1.项目中的强耦合问题
    public class UserDaoImpl implements UserDao{...}
    
    public class UserServiceImpl implements UserService{
    	// !!!强耦合了UserDaoImpl,使得UserServiceImpl变得不稳健
    	private UserDao userDao = new UserDaoImpl();
    	@Override
    	public User queryUser(){
    		return userDao.queryUser();
    	}
    }
    
    2.解决方案
    // 不引用任何一个具体的组件(实现类),在需要其他组件的位置预留存取值入口(set/get)
    public class UserServiceImpl implements UserService{
        // 不在耦合任何DAO实现!!!,消除不稳健因素
        private UserDao userDao;
        // 为userDao定义set/get,允许userDao属性接受spring赋值
        // Getter and Setter
        @Override
        public User queryUser(){
            return userDao.queryUser();
        }
    }
    
    <bean id="userDAO" class="com.qf.UserDaoImpl"></bean>
    <!-- UserServiceImpl组件 -->
    <bean id="userService" class="com.qf.UserServiceImpl">
    	<!-- 由spring为userDAO赋值,值为id="userDAO"的bean -->
    	<property name="userDAO" ref="userDAO"/>
    </bean>
    

    此时,如果需要更换其他UserDao实现类,则UserServiceImpl不用任何改动!

    则此时的UserServiceImpl组件变得更加稳健!

    3.DI(Dependency Injection)依赖注入【重点】


    1. 概念

    在Spring创键对象的同时,为其属性赋值,称为依赖注入。

    注入分类:
    1.Set注入:创建对象时,Spring工厂会通过Set方法为对象的属性赋值。
    2.自建类型注入:创键次要bean作为属性,为主要bean赋值
    3.构造注入:创建对象时,Spring工厂会通过构造方法为对象的属性赋值.
    4.自动注入:不用再配置中指定为哪个属性赋值,及赋什么值,
    由Spring自动根据某个"原则",在工厂中找一个bean,为属性注入属性值.
    
    2. Set注入

    创建对象时,Spring工厂会通过Set方法为对象的属性赋值。 -- bean对象必须由setter和getter方法

    文件结构

    2.0 配置文件 - pom.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.qf.edu</groupId>
        <artifactId>SpringLearn</artifactId>
        <version>1.0-SNAPSHOT</version>
        <dependencies>
            <!--Spring 工厂 依赖-->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>5.3.15</version>
            </dependency>
    		<!-- 单元测试 -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-test</artifactId>
                <version>5.3.15</version>
            </dependency>
            <dependency>
                <groupId>org.junit.jupiter</groupId>
                <artifactId>junit-jupiter</artifactId>
                <version>RELEASE</version>
                <scope>compile</scope>
            </dependency>
        </dependencies>
    
        <build>
            <resources>
                <resource>
                    <directory>src/main/java</directory>
                    <includes>
                        <include>*.xml</include>
                        <include>**/*.xml</include>
                    </includes>
                    <filtering>true</filtering>
                </resource>
    
                <resource>
                    <directory>src/main/resources</directory>
                    <includes>
                        <include>*</include>
                        <include>**/*</include>
                    </includes>
                    <filtering>true</filtering>
                </resource>
            </resources>
        </build>
    
    </project>
    
    2.1 定义目标Bean类型 - User.java
    import java.util.*;
    
    public class User {
        private Integer id;
        private String password;
        private String sex;
        private Integer age;
        private Date bornDate;
        private String[] hobbys;
        private List<String> names;
        private Properties files;
        private Map<String,String> countries;
        private Set<String> phones;
    
        // getter and setter
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        public String getSex() {
            return sex;
        }
    
        public void setSex(String sex) {
            this.sex = sex;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        public Date getBornDate() {
            return bornDate;
        }
    
        public void setBornDate(Date bornDate) {
            this.bornDate = bornDate;
        }
    
        public List<String> getNames() {
            return names;
        }
    
        public String[] getHobbys() {
            return hobbys;
        }
    
        public void setNames(List<String> names) {
            this.names = names;
        }
    
        public Properties getFiles() {
            return files;
        }
    
        public void setFiles(Properties files) {
            this.files = files;
        }
    
        public Map<String, String> getCountries() {
            return countries;
        }
    
        public void setCountries(Map<String, String> countries) {
            this.countries = countries;
        }
    
        public Set<String> getPhones() {
            return phones;
        }
    
        public void setPhones(Set<String> phones) {
            this.phones = phones;
        }
    
        public void setHobbys(String[] hobbys) {
            this.hobbys = hobbys;
        }
    }
    
    2.2 基本类型 + 字符串类型 + 日期类型 + 容器类型 spring-context.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           https://www.springframework.org/schema/beans/spring-beans.xsd">
        <!--Set injection-->
        <bean id="u1" class="User">
            <!-- base field -->
            <property name="id" value="1"/>
            <property name="password" value="123"/>
            <property name="sex" value="male"/>
            <property name="age" value="21"/>
            <property name="bornDate" value="2000/4/30"/><!-- 注意格式"/" -->
            <!--array-->
            <property name="hobbys">
                <array>
                    <value>Run</value>
                    <value>Sleep</value>
                </array>
            </property>
            <!--Set-->
            <property name="phones">
                <set>
                    <value>123</value>
                    <value>234</value>
                </set>
            </property>
            <!--List-->
            <property name="names">
                <list>
                    <value>tom</value>
                    <value>jack</value>
                </list>
            </property>
            <!--Map-->
            <property name="countries">
                <map>
                    <entry key="CN" value="China"/>
                    <entry key="US" value="America"/>
                </map>
            </property>
            <!--Properties-->
            <property name="files">
                <props>
                    <prop key="first">One</prop>
                    <prop key="second">Two</prop>
                </props>
            </property>
         </bean>
    </beans>
    
    2.3 测试Set注入 -- TestUser.java
    import org.junit.jupiter.api.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    // Set注入
    public class TestUser {
        @Test
        public void t(){
            // 创键spring-context对象
            ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-context.xml");
            // 通过工厂反射处user对象
            User user = (User) ctx.getBean("u1");
            System.out.println(user.getSex());
            System.out.println(user.getBornDate());
            // 字符串array
            for (String hobby : user.getHobbys()) {
                System.out.print(hobby+" ");
            }
            // map
            for (String value : user.getCountries().values()) {
                System.out.print(value+" ");
            }
        }
    }
    
    3.自建类型注入

    把次要bean作为属性,为主要bean赋值

    3.1 spring-context.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           https://www.springframework.org/schema/beans/spring-beans.xsd">
        <!--definition type injection -->
    	<!-- 次要bean ,作为主题的属性注入 Address和AddressDemo都和resource目录同一级别 -->
        <bean id="addr" class="Address">
            <property name="position" value="北京市海淀区"/>
            <property name="zipCode" value="100001"/>
        </bean>
        <!-- 主要bean ,操作的主体-->
        <bean id="ad" class="AddressDemo">
            <property name="address" ref="addr"/>
        </bean>
    </beans>
    
    3.2 pom.xml同上
    3.3 Address.java
    public class Address {
        private String position;
        private String zipCode;
    
        public String getPosition() {
            return position;
        }
    
        public void setPosition(String position) {
            this.position = position;
        }
    
        public String getZipCode() {
            return zipCode;
        }
    
        public void setZipCode(String zipCode) {
            this.zipCode = zipCode;
        }
    }
    
    3.4 AddressDemo.java
    public class AddressDemo {
        private Address address;
    
        public Address getAddress() {
            return address;
        }
    
        public void setAddress(Address address) {
            this.address = address;
        }
    }
    
    3.4 测试
    import org.junit.jupiter.api.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class StudentTest {
        @Test
        public void t(){
            ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-context.xml");
            Student st = (Student) ctx.getBean("s");
            st.show();
        }
    }
    
    4.构造注入

    3.构造注入:创建对象时,Spring工厂会通过构造方法为对象的属性赋值.

    4.1 pom.xml同上
    4.2 Bean对象 - Student.java
    public class Student {
        private Integer id;
        private String name;
        private String sex;
        private Integer age;
    
        // Constructors
    
        public Student(Integer id, String name, String sex, Integer age) {
            this.id = id;
            this.name = name;
            this.sex = sex;
            this.age = age;
        }
        public void show(){
            System.out.println("id:"+id);
            System.out.println("name:"+name);
            System.out.println("sex:"+sex);
            System.out.println("age:"+age);
        }
    }
    
    4.3 spring-context.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           https://www.springframework.org/schema/beans/spring-beans.xsd">
        <!-- constuctor injection -->
        <bean id="s" class="Student">
        	<!-- name == index -->
            <constructor-arg index="0" value="1234"/>
            <constructor-arg index="1" value="tom"/>
            <constructor-arg index="2" value="male"/>
            <constructor-arg index="3" value="20"/>
        </bean>
    </beans>	
    
    4.4 测试 StudentTest
    import org.junit.jupiter.api.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class StudentTest {
        @Test
        public void t(){
            ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-context.xml");
            Student st = (Student) ctx.getBean("s");
            st.show();
        }
    }
    
    5.自动注入【了解】

    不用再配置中指定为哪个属性赋值,及赋什么值。

    有spring自动根据某个“原则”,在工厂中查找一个bean,为属性注入属性值

    4.Bean细节


    1.控制简单对象的单例、多例模式
    sprint-context.xml
    <bean scope="singleton|prototype"/>
    
    <!-- 
    	singleton(默认):每次调用工厂,得到的都是同一个对象
    	prototype:每次调用工厂,都会创建新的对象
    -->
    <bean id="mc" class="MyClass" scope="singleton"/>
    
    • 注意:需要根据场景决定对象的单例、多例模式
    • 可以共用:Servie,DAO,SqlSessionFactory(或者所有工厂)
    • 不可共用:Connection,SqlSession,ShoppingCart

    5.Spring工厂


    1.饿汉式创键优势

    工厂创建后,会将Spring配置文件中的所有对象都创建完成(饿汉式).

    提高程序运行效率。避免多次IO,减少对象创建时间。(类似于连接池)

    2.生命周期方法
    • 自定义初始化方法:添加"init-method"属性,Spring则会在创建对象之后,调用此方法.
    • 自定义销毁方法:添加"destory-method"属性,Spring则会在销毁对象之前,调用此方法
    • 销毁:工厂的close()方法被调用之后,Spring会毁掉所有已创键的单例对象
    • 分类:Singleton对象由Spring容器销毁、Prototype对象由JVM销毁
    3.生命周期注解
    初始化注解:@PostConstruct
    销毁注解:@PreDestory
    
    4.生命周期阶段
    单例Bean:singleton
    随工厂启动 创键=> 构造方法 => set方法(注入值) => init(初始化) => 构建完成 => 随工厂关闭销毁
    
    多例Bean:prototype
    被使用 创键 => 构造方法 => set方法(注入值) => init(初始化) => 构建完成 =>JVM垃圾回收销毁
    

    6.AOP(面向切面编程) - Aspect Oriented Programming【思想重点,在spring和mvc种一般不用,但必须会思想】

    AOP,即面向切面编程,利用一种称为"横切"的技术,抛开封装的对象内部,并将那些影响了多个磊的公共行为封装到一个可重用模块,并将其名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,缺位业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。

    0.实现原理

    使用动态代理技术

    1. 基于接口的JDK官方的动态代理(优先使用)
    2. 基于子类的第三方的cglib的动态代理
    3. 基于Spring的动态代理ProxyFactory
    1.AOP开发术语
    • 连接点(Joinpoint):连接点是程序类中客观存在的方法,可被Spring拦截并切入内容。
    • 切入点(Pointcut):被Spring切入连接点。
    • 通知、增强(Advice):可以为切入点添加额外功能,分为:前置通知,后置通知,异常通知,环绕通知等。
    • 目标对象:代理的目标对象
    • 引介(Introduction):一种特殊的增强,可以在运行期为动态类添加Field和Method。
    • 织入(Weaving):把通知应用到具体的类,进而创键新的代理类的过程。
    • 代理(Proxy):被AOP织入通知后,产生的结果类。
    • 切面(Aspect):由切点和通知组成,将横切逻辑织入切面所指定的连接点中。
    2.作用

    Spring的AOP编程即是通过动态代理类为原始类的方法添加辅助功能。

    在程序运行期间,不修改源码对已有方法进行增强

    3.环境搭建

    引入AOP相关依赖

    <!--spring aop-->
    <dependency>
    	<groupId>org.springframework</groupId>
    	<artifactId>spring-aspects</artifactId>
    	<version>5.3.15</version>
    </dependency>
    

    spring-context.xml引入AOP命名空间

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"   <!--spring context -->
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:aop="http://www.springframework.org/schema/aop"
               
            <!--spring context -->
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           https://www.springframework.org/schema/beans/spring-beans.xsd
            <!--spring context -->
                
           http://www.springframework.org/schema/aop 
           http://www.springframework.org/schema/aop/spring-aop.xsd">
    </beans>       
    
    4.开发流程

    定义原始类

    UserService.java
    package com.qf.aaron.aop.basic;
    // 原始类
    public interface UserService {
        public void save();
    }
    
    UserServiceImpl.java
    package com.qf.aaron.aop.basic;
    // 原始类
    public class UserServiceImpl implements UserService{
        public void save() {
            System.out.println("save method executed...");
        }
    }
    

    定义通知类(添加额外功能)

    package com.qf.aaron.aop.basic;
    
    import org.springframework.aop.MethodBeforeAdvice;
    import java.lang.reflect.Method;
    
    public class MyAdvice implements MethodBeforeAdvice {
         // 实现前置通知接口
        public void before(Method method, Object[] args, Object target) throws Throwable {
            System.out.println("before advice executed");
        }
     }
    

    定义bean标签 - spring-context.xml

    <!-- 原始对象 -->
    <bean id="us" class="com.qf.aaron.aop.basic.UserServiceImpl"/>
    <!-- 辅助对象 -->    
    <bean id="myAdvice" class="com.qf.aaron.aop.basic.MyAdvice"/>
    

    定义切入点(PointCut)

    形成切面

    <aop:config>
    	<!-- 切点 -->
    	<aop:pointcut id="myPonitCut" expression="execution(* save())"/>
    </aop:config>	
    
    <aop:config>
    	<!-- 组装切面 -->
    	<aop:advisor advice-ref="myAdvice" pointcut-ref="myPointCut"/>
    </aop:config>	
    
    5.通知类【可选】

    定义通知类,达到通知效果 -- 神魔时候做什莫

    前置通知:MethodBeforeAdvice
    后置通知:AfterAdvice
    后置通知:AfterReturningAdvice //有异常不执行,方法会因异常而结束,无返回值
    异常通知:ThrowsAdvice
    环绕通知:MethodInterceptor
    
    6.通配切入点 - 切点表达式

    根据表达式通配切入点

    execution(
        [访问修饰符]
        [返回类型]
        [全限定类名 . ] 
        访问名
        (参数类型 | ".." , ... ) 
        [ throws 异常类型 ]
    )
    <!-- 匹配参数 -->
    <aop:pointcut id="myPointCut" expression="execution(* *(com.qf.aaron.aop.basic.User))"/>
    <!-- 匹配方法名(无参) -->
    <aop:pointcut id="myPointCut" expression="execution(* save())"/>
    <!-- 匹配方法名(任意参数) -->
    <aop:pointcut id="myPointCut" expression="execution(* save(String s))"
    <!-- 匹配返回值类型 -->
    <aop:pointcut id="myPointCut" expression="execution(com.qf.aaron.aop.basic.User *(参数))"/>
    <!-- 匹配类名 -->
    <aop:pointcut id="myPointCut" expression="execution(* com.qf.aaron.aop.basic.UserServiceImpl.*(参数))"/>
    <!-- 匹配包名 -->
    <aop:pointcut id="myPointCut" expression="execution(* com.qf.aaron.aop.basic.*.*(参数))"/>
    <!-- 匹配包名、以及子包名 -->
    <aop:pointcut id="myPointCut" expression="execution(* com.qf.aaron.aop..*.*(参数))"/>
    
    7.JDK和CGLIB选择
    • spring底层,包含了jdk代理和cglib代理两种动态代理生成机制
    • 基本规则是:目标业务类如果有接口则用JDK代理,没有接口则用CGLib代理
    class DefaultAopProxyFactory{
    	// 该方法中明确定义了 JDK代理和CGLib代理的选取规则
    	// 基本规则是:目标业务中如果有接口则用JDK代理,没有接口则用CGLib代理
    	public AopProxy createAopProxy(){
    		...
    	}
    }
    
    8.后处理器
    • spring中定义了很多后处理器;
    • 每个bean对象在创键完成之前,都会有一个后处理过程,即在加工,对bean做出相关改变和调整;
    • spring-AOP中,就有一个专门的后处理器,负责通过原始业务组件(Service),再加工得到一个代理组件。

    后处理器的定义 - MyBeanPostProcessor.java
    package com.qf.aaron.aop.basic;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.BeanPostProcessor;
    
    /**
     * 定义在bean后处理器
     * 作用:在bean的创键之后,进行再加工
     */
    public class MyBeanPostProcessor implements BeanPostProcessor {
        /**
         * 在bean的init方法之前执行
         * @param bean 原始的bean对象
         * @param beanName
         * @return
         * @throws BeansException
         */
        public Object postProcessBeforeInitialization(Object bean,String beanName) throws BeansException{
            System.out.println("后处理器 在init之前执行"+bean.getClass());
            return bean;
        }
    
        /**
         * 在bean的init方法之后执行
         * @param bean
         * @param beanName
         * @return
         * @throws BeansException
         */
        public Object postProcessAfterInitialization(Object bean,String beanName) throws BeansException{
            System.out.println("后处理器 在init之后执行~~~"+bean.getClass());
            return bean;// 此处返回的是getBean()最终的结果
        }
    }
    
    配置后处理器
    <!-- 配置后处理器,将对工厂中所有的bean生命周期进行干预 -->
    <bean class="com.tx.beanpostprocessor.MyBeanPostProcessor"/>
    
    bean生命周期
    构造 => 注入属性 满足依赖 => 后处理器前置过程 => 初始化 => 后处理器后置过程 => 返回 => 销毁
    

    7. 注解开发【重点】


    1.声明bean

    用于替换自建类型的标签;可以更快速的声明bean

    @Service 业务类专用

    @Repository dao实现类专用

    @Controller web层专用

    @Component :IoC注解,用于描述一个类,当Spring容器扫描到此类之后,将此类的实例放到Spring容器中,默认情况下,容器bean的id为类名的大驼峰-》小驼峰

    如果不想默认,显示指定为@Component("userService")

    @Scope 用户控制bean的创键模式

    @Service注解 -- 可以带参数,也可以不带
    // @Service说明 此类是一个业务类,需要将此类纳入工厂
    // @Service默认beanId 是 首字母小写的类名 eg:"userServiceImpl"
    // @Service("userService") 自定义beanId为"userService"
    @Service // 声明bean,且id="userServiceImpl"
    @Scope("singleton") // 声明bean对象创键模式,默认单例模式;@Scope("prototype")为设置多例模式
    public class UserServiceImpl implements UserService{
    	...
    }
    
    @Service
    @Scope
    == spring-context.xml中的<bean id=首字母小写类名 class=xx scope=xx/>
    
    2.注入(DI)

    用于完成bean中属性值的注入

    • @Autowired 基于类型的自动注入
    • @Resource 基于名称自动注入
    • @Qualifier("userDao") ,限定要注入的bean的id,和@Autowired配合使用
    • @Value 注入简单类型数据(jdk8种+String)
    @Service
    public class UserServiceImpl implements UserService{
    	@Autowired //注入类型为UserDAO的bean
    	@Qualifier("userDAO2")   // 如果有多个类型为UserDao的bean,可以用此注解从中挑选一个
    	private UserDAO userDAO;
    	@Resource("userDAO3")
    	private UserDAO userDAO1;
    	@Value("100")  // 注入数字
    	private Integer id;
    }
    
    3.事务控制

    用于控制事务切入

    • @Transactional
    • 工厂配置中的<tx:advice...和<aop:config...可以省略!!

    1655272376525

    4.注解所需要的配置 spring-context.xml
    <!-- 告知sping,哪些包有被注解的类、方法、属性 -->
    <!-- <context:component-scan base-package=""></context:component-scan> -->
    <context:component-scan base-package="com.tx"></context:component-scan>
    <!-- 告知spring,@Transcational在定制事务时,基于txManager=DataSourceTransactionManager -->
    <tx:annotation-driven transaction-manager="txManager"/>
    
    5.AOP开发 -- 使用注解
    使用注解


    AOP使用注解配置
    <!-- 添加配置如下,启用aop注解 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    
    6. 生命周期注解
    @PostConstruct:生命周期注解,在此SpringBean实例化之后,执行此注解描述的方法
    @PreDestory:生命周期注解,在此SpingBean销毁之前,执行此注解所描述的方法
    
  • 相关阅读:
    linux 操作系统 基础
    [HAOI2011]Problem A
    [HNOI2015] 菜肴制作
    [P3676]小清新数据结构题
    [NOI2016]区间
    [BOI2007]Mokia 摩基亚
    [NOI2012]美食节
    [CQOI2015]网络吞吐量
    [六省联考2017]期末考试
    [HNOI2015]亚瑟王
  • 原文地址:https://www.cnblogs.com/nanfengnan/p/16378290.html
Copyright © 2020-2023  润新知