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.实现原理
使用动态代理技术
- 基于接口的JDK官方的动态代理(优先使用)
- 基于子类的第三方的cglib的动态代理
- 基于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...可以省略!!
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销毁之前,执行此注解所描述的方法

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号