Spring框架学习总结

本文详细介绍了Spring框架中的关键概念,包括IoC容器的三种bean实例化方式、依赖注入的构造器注入和setter注入、自动装配以及bean的生命周期。此外,还讨论了Spring的AOP支持,如切面、通知类型和声明式事务管理。最后,文章涵盖了事务管理的编程式和声明式方法,以及相关的配置和注解。
摘要由CSDN通过智能技术生成

1 实例化bean的三种方法

①使用构造函数实例化

ApplicationContext Context = new ClassPathXmlApplicationContext("SpringIoc.xml");
UserDao bean = (UserDao) Context.getBean("subsystemA-dataSource");
<bean id="userDao" name="userDao" class="com.cql.Dao.UserDao">
    <!-- collaborators and configuration for this bean go here -->
</bean>
<alias name="userDao" alias="subsystemA-dataSource"/>

public class UserService {
    private static final UserService userService = new UserService();
    private UserDao userDao;
    private AddressDao addressDao;
    private UserService(){

    }
    public UserService(UserDao userDao, AddressDao addressDao) {
        this.userDao = userDao;
        this.addressDao = addressDao;
    }

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public void setAddressDao(AddressDao addressDao) {
        this.addressDao = addressDao;
    }

    public static UserService createUserService(){
        return userService;
    }
    public UserDao USCreateUserDao(){
        return new UserDao();
    }
}

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

ApplicationContext Context1 = new ClassPathXmlApplicationContext("SpringIoc.xml");
UserService userService = (UserService) Context.getBean("service");
UserDao userdao = userService.USCreateUserDao();
<bean id="userService" name="service" class="com.cql.Service.UserService" factory-method="createUserService">
	<!-- collaborators and configuration for this bean go here -->
</bean>

③使用实例工厂方法实例化

ApplicationContext Context = new ClassPathXmlApplicationContext("SpringIoc.xml");
UserDao userDao = (UserDao) Context.getBean("userDao_in_Service");
<bean id="userService" name="service" class="com.cql.Service.UserService" factory-method="createUserService">
    <!-- collaborators and configuration for this bean go here -->
</bean>

<bean id="userDao_1" name="userDao_in_Service" factory-bean="service" factory-method="USCreateUserDao">
    <!-- collaborators and configuration for this bean go here -->
</bean>

2 IoC容器

2.1 依赖注入

        DI主要有以下两种方式:①Constructor-based依赖注入,基于构造器的依赖注入,本质上是使用构造器给成员变量赋值。②Setter-based依赖注入,基于setter方法的依赖注入,本质上是使用set方法给成员变量赋值。

①构造器注入

ApplicationContext Context = new ClassPathXmlApplicationContext("SpringIoc.xml");
UserService userService = (UserService) Context.getBean("userServiceC");
userService.PrintConstruct();
<!--  利用bean通过构造函数构造对象,构造器注入  -->
<!-- constructor-arg中有index属性,用于指明UserService中构造器的参数顺序,有name属性,用于指明构造器的参数名字,避免歧义 -->
<bean name="userServiceC" class="com.cql.Service.UserService">
	<constructor-arg ref="userDaoSC"/>
	<constructor-arg ref="addressDaoSC"/>
</bean>
<bean id="userDaoSC" class="com.cql.Dao.UserDao">
</bean>
<bean id="addressDaoSC" class="com.cql.Dao.AddressDao">
</bean>

 ②setter注入

ApplicationContext Context = new ClassPathXmlApplicationContext("SpringIoc.xml");
UserService userService = (UserService) Context.getBean("userServiceS");
userService.PrintConstruct();
<!--  利用bean通过setter构造对象,setter注入  -->
<bean name="userServiceS" class="com.cql.Service.UserService">
	<property name="userDao" ref="userDaoSS"/>
	<property name="addressDao" ref="addressDaoSS"/>
</bean>
<bean id="userDaoSS" class="com.cql.Dao.UserDao">
</bean>
<bean id="addressDaoSS" class="com.cql.Dao.AddressDao">
</bean>

2.2 自动装配

        Spring容器可以自动装配引用数据类型---协作bean之间的关系。自动装配可以显著减少指定属性或构造函数参数的需要,还可以随着对象的发展更新配置。bean的autowire属性,有no、byName、byType和constructor,在需要自动装配引用数据类型的bean中添加该属性,便可实现自动装配。

2.3 bean的生命周期

        ①创建回调和销毁回调--实现接口,重写方法。

public class People implements InitializingBean, DisposableBean {
}

        ②不推荐实现接口,这样会与Spring藕合在一起,而是使用bean的两个属性,在people类中实现init和cleanup方法。

<bean id="people" class="com.cql.entity.People" init-method="init">
</bean>
​
<bean id="people" class="com.cql.entity.People" destroy-method="cleanup">
</bean>

        ③也可以使用注解来操作。

<!--依赖-->
<dependency>
    <groupId>javax.annotation</groupId>
    <artifactId>javax.annotation-api</artifactId>
    <version>1.3.2</version>
</dependency>
<!--beans修改-->
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
    <context:annotation-config/>  
    <!--开启注解-->
</beans>
//java代码中的函数添加注解
@PostConstruct
public void initC(){
	System.out.println("CCInit!!!");
}
@PreDestroy
public void destroyC(){
	System.out.println("CCDestroy!!!");
}

        ④在beans中定义全局默认的init和destroy方法,只要类中声明了同名方法,便可实现相应功能。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd" default-init-method="init" default-destroy-method="destroy">

    <!--开启注解-->
    <context:annotation-config/>

</beans>

2.4 classpath扫描和组件管理

        通过扫描类的注解来进行容器填充,而不是通过xml文件的读取。@Component 是任何spring管理组件的通用注解,只要在类上添加了该注解,便是定义了一个bean。@Repository@Service@Controller是比@Component用于更具体用例的注解(分别代表持久层业务层控制层),这些注解对后期对特定bean进行批量处理时是有帮助。

【常用方法】

//在所有需要注入的类上添加注解@Component(通用注解)/@Repository(持久层)/@Service(业务层)/@Controller(控制层)
//指定一个包名,自动扫描会检测这个包"org.example"及其子包下的所有类信息。
@Configuration
@ComponentScan(basePackages = "org.example")
public class AppConfig  {
}

<?xml version="1.0" encoding="UTF-8"?>
<beans 
    <context:annotation-config/>
    <bean name="appConfig" class="com.cql.AppConfig"/>
</beans>

ApplicationContext Context = new ClassPathXmlApplicationContext("AnnotationIoC.xml");
Pet pet = Context.getBean(Pet.class);
System.out.println(pet);

2.5 环境抽象

public void DataSourceConfigTest(){
    //1.创建容器
    AnnotationConfigApplicationContext aCAContext = new AnnotationConfigApplicationContext();
    //2.激活环境
    aCAContext.getEnvironment().setActiveProfiles("pro");
    //3.打包
    aCAContext.scan("spring.dataSource");
    //4.刷新
    aCAContext.refresh();
    DataSource bean = aCAContext.getBean(DataSource.class);
    System.out.println(bean);
}

 2.6 事件监听机制

         【实现监听事件】的两种方法:

        ①实现ApplicationListener接口,重写onApplicationEvent()方法。

@Component
public class EmailListener implements ApplicationListener<OrderEvent> {
    @Override
    public void onApplicationEvent(OrderEvent event) {
        System.out.println("Email监听到了");
    }

}

        ②利用@EventListener注解来监听。

@Component
public class MsgListenerAnno {
    @EventListener
    public void msgListenerAnnoWay(OrderEvent event){
        System.out.println("发送消息到手机...");
    }
}

        【发布自定义事件】--分两步

        ①OrderEvent实体类继承ApplicationEvent类。

public class OrderEvent extends ApplicationEvent {
    /**
     * Create a new {@code ApplicationEvent}.
     *
     * @param source the object on which the event initially occurred or with
     *               which the event is associated (never {@code null})
     */
    public OrderEvent(Object source) {
        super(source);
    }
}

        ②实现ApplicationEventPublisherAware接口

public class OrderService implements ApplicationEventPublisherAware {
    private ApplicationEventPublisher applicationEventPublisher;
    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.applicationEventPublisher = applicationEventPublisher;
    }
    public void SendMsg(Order orderService){
        applicationEventPublisher.publishEvent(orderService);
    }
}
public void ServiceTest(){
    ApplicationContext Context = new AnnotationConfigApplicationContext(AppConfig.class);
    OrderService orderService = new OrderService();
    orderService.setApplicationEventPublisher(Context);
    orderService.SendMsg(new OrderEvent(new Order(1, "鸡腿")));
}

3 AOP

        要在Spring配置中使用@AspectJ注解,您需要启用Spring支持,以便基于@AspectJ注解配置Spring AOP,如果Spring确定一个bean被一个或多个切面通知,它将自动为该bean生成一个代理,以拦截方法调用,并确保通知在需要时运行。

@Component
@ComponentScan(basePackages = "com.cql")
@EnableAspectJAutoProxy
public class AppConfig {
}
@Aspect
@Component
public class MyAspectJAnno {
    /**
     * 声明一个切点,pointCut()指向execution中定义的com.cql类下的所有public方法
     */
    @Pointcut("execution(public * com.cql..*(..))")
    private void pointCut(){
    }

    @DeclareParents(value="com.cql.service.Impl.OrderService",defaultImpl= MeuService.class)
    public static IMeuService meuServiceWay;

    @Before("pointCut()")
    private void beforeAdvice(JoinPoint jp){
        System.out.println("this is before Advice 1");
        MethodSignature signature = (MethodSignature)jp.getSignature();
        Method method = signature.getMethod();
        try {
            method.invoke(jp.getTarget(), jp.getArgs());
        } catch (IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }
        System.out.println("this is before Advice 2");
    }

    @AfterThrowing(value = "execution(public * com.cql..*(..))", throwing="ex")
    public void afterThrowingAdvice(ArithmeticException ex) {
        System.out.println("this is afterThrowing Advice");
        System.out.println("========================>" + ex);
    }

    @AfterReturning("pointCut()")
    private void afterReturningAdvice(){
        System.out.println("this is afterReturningAdvice");
    }
    @After("pointCut()")
    private void afterAdvice(){
        System.out.println("this is after Advice");
    }

    /**
     * around可用于事务的增强
     * @param pjp
     * @return
     */
    @Around("pointCut()")
    private Object aroundAdvice(ProceedingJoinPoint pjp){
        System.out.println("this aroundAdvice before");
        // 这里是真正bean的方法调用的地方
        try {
            pjp.proceed();
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
        System.out.println("this aroundAdvice after");
        return null;
	}
}

4 事务

4.1 编程式事务

        编程式事务比较少用,使用【TransactionTemplate】绝对会将您与Spring的事务基础设施和api耦合在一起。

        Spring Framework提供了两种编程式事务管理的方法:

        ①使用TransactionTemplate

public void transferMoney3(String from, String to, Integer money) {
    transactionTemplate.execute(new TransactionCallbackWithoutResult() {
        @Override
        protected void doInTransactionWithoutResult(TransactionStatus status) {
            // 转账其实是两个语句
            String moneyFrom = "update spring_tx set salary = salary - ? where name = ? ";
            String moneyTo = "update spring_tx set salary = salary + ? where name = ? ";
            // 从转账的人处扣钱
            jdbcTemplate.update(moneyFrom, money, from);
            jdbcTemplate.update(moneyTo, money, to);
        }
    });
}

        ②使用 TransactionManager

public void transferMoney2(String from, String to, Integer money) {
    // 默认的事务配置
    DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
    // 使用事务管理器进行事务管理
    TransactionStatus transaction = transactionManager.getTransaction(definition);
    // 转账其实是两个语句
    String moneyFrom = "update spring_tx set salary = salary - ? where name = ? ";
    String moneyTo = "update spring_tx set salary = salary + ? where name = ? ";
    try{
        // 从转账的人处扣钱
        jdbcTemplate.update(moneyFrom, money, from);
        //            int i = 1/0;
        jdbcTemplate.update(moneyTo, money, to);
    } catch (RuntimeException e){
        e.printStackTrace();
        transactionManager.rollback(transaction);
    }
    transactionManager.commit(transaction);
}

【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"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx https://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <context:property-placeholder location="jdbc.properties"/>
    <context:component-scan base-package="com.cql"/>

    <!--  注入事务管理器  -->
    <bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
     </bean>

    <!--  JDBC样板  -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
        <property name="transactionManager" ref="dataSourceTransactionManager"/>
    </bean>

    <!--  数据源  -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="url" value="${jdbc.URL}"/>
        <property name="driverClassName" value="${jdbc.driverName}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

</beans>

4.2 声明式事务

        大多数Spring框架用户选择声明式事务管理。 该选项对应用程序代码的影响最小,因此最符合非侵入式轻量级容器的理想。

        Spring框架的声明式事务通过AOP代理进行实现,事务的通知是由AOP元数据与事务性元数据的结合产生了一个AOP代理,该代理使用【TransactionInterceptor】结合适当的【TransactionManager】实现来驱动方法调用的事务。

        Spring Framework的【TransactionInterceptor】为命令式和响应式编程模型提供了事务管理。 拦截器通过检查方法返回类型来检测所需的事务管理风格。 事务管理风格会影响需要哪个事务管理器。 命令式事务需要【PlatformTransactionManager】,而响应式事务使用【ReactiveTransactionManager 】实现。

        【@Transactional 】通常用于【PlatformTransactionManager 】管理的【线程绑定事务】,将事务暴露给当前执行线程中的所有数据访问操作。(注意:这不会传播到方法中新启动的线程)。

【Xml形式】

【自定义事务通知】

<aop:config>
    <aop:pointcut id="point" expression="execution(* com.cql.service..*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="point"/>
</aop:config>
<bean id="txAdvice" class="com.cql.AOP.TXAdvice">
    <property name="transactionManager" ref="dataSourceTransactionManager"/>
</bean>
public class TXAdvice implements MethodInterceptor {
    private PlatformTransactionManager transactionManager;

    public void setTransactionManager(PlatformTransactionManager transactionManager) {
        this.transactionManager = transactionManager;
    }

    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        // 默认的事务配置
        DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
        // 使用事务管理器进行事务管理
        TransactionStatus transaction = transactionManager.getTransaction(definition);

        Object invoke = null;
        try{
            invoke = methodInvocation.getMethod().invoke(methodInvocation.getThis(), methodInvocation.getArguments());
        }catch (RuntimeException e){
            e.printStackTrace();
            transactionManager.rollback(transaction);
        }
        transactionManager.commit(transaction);
        return invoke;
    }
}

【官方事务通知】

<!-- the transactional advice (what 'happens'; see the <aop:advisor/> bean below) -->
<tx:advice id="txAdvice" transaction-manager="dataSourceTransactionManager">
    <!-- the transactional semantics... -->
    <tx:attributes>
        <!-- all methods starting with 'get' are read-only -->
        <tx:method name="get*" read-only="true"/>
        <!-- other methods use the default transaction settings (see below) -->
        <tx:method name="*"/>
    </tx:attributes>
</tx:advice>

<!-- ensure that the above transactional advice runs for any execution
        of an operation defined by the FooService interface -->
<aop:config>
    <aop:pointcut id="point" expression="within(com.cql.service..*)"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="point"/>
</aop:config>

【统一事务执行代码】

public void transferMoney1(String from, String to, Integer money) {
    // 转账其实是两个语句
    String moneyFrom = "update spring_tx set salary = salary - ? where name = ? ";
    String moneyTo = "update spring_tx set salary = salary + ? where name = ? ";
    // 从转账的人处扣钱
    jdbcTemplate.update(moneyFrom, money, from);
    jdbcTemplate.update(moneyTo, money, to);
}

【注解形式】

@Transactional
@Transactional
public void transferMoney1(String from, String to, Integer money) {
    // 转账其实是两个语句
    String moneyFrom = "update spring_tx set salary = salary - ? where name = ? ";
    String moneyTo = "update spring_tx set salary = salary + ? where name = ? ";
    // 从转账的人处扣钱
    jdbcTemplate.update(moneyFrom, money, from);
    int i =1/0;
    jdbcTemplate.update(moneyTo, money, to);
}
<!--在xml中开启事务注解-->
<tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>

5 依赖配置总结

<!--Spring核心依赖-->
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-context</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-core</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-beans</artifactId>
</dependency>

<!--Spring开启注解依赖-->
<dependency>
    <groupId>javax.annotation</groupId>
    <artifactId>javax.annotation-api</artifactId>
    <version>1.3.2</version>
</dependency>

<!--切面编程所需依赖-->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.19</version>
</dependency>

<!--Spring事务依赖-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>6.0.6</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>6.0.6</version>
</dependency>

 6 配置文件总结

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       <!--开启p命名空间-->
       xmlns:p="http://www.springframework.org/schema/p"
       <!--开启c命名空间-->
       xmlns:c="http://www.springframework.org/schema/c"
       <!--开启事务-->
       xmlns:tx="http://www.springframework.org/schema/tx"
       <!--开启aop-->
       xmlns:aop="http://www.springframework.org/schema/aop"
       <!--开启注解-->
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx https://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

</beans>

        通过配置文件注入bean

<?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">

    <!--1.使用构造函数实例化-->
    <bean id="userDao" name="userDao" class="com.cql.Dao.UserDao">
        <!-- collaborators and configuration for this bean go here -->
    </bean>
    <!--起别名-->
    <alias name="userDao" alias="subsystemA-dataSource"/>

    <bean id="userService" name="service" class="com.cql.Service.UserService" factory-method="createUserService">
        <!-- collaborators and configuration for this bean go here -->
    </bean>

    <bean id="userDao_1" name="userDao_in_Service" factory-bean="service" factory-method="USCreateUserDao">
        <!-- collaborators and configuration for this bean go here -->
    </bean>
    <!-- more bean definitions go here -->

</beans>

        【AspectJ代理】 

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

    <aop:config>
        <!--    定义切面    -->
        <aop:aspect ref="aopXml">
            <!--      定义切点      -->
            <aop:pointcut id="point" expression="execution(* com.cql.service.Impl.OrderService.order(..))"/>
            <!--  pointcut="execution(* com.cql..*(..))"  -->
            <aop:before method="beforeAdvice" pointcut-ref="point" />
            <aop:after-throwing method="afterThrowingAdvice" throwing="ex" pointcut-ref="point"/>
            <aop:after-returning method="afterReturningAdvice" pointcut-ref="point"/>
            <aop:after method="afterAdvice" pointcut-ref="point"/>
<!--            <aop:around method="aroundAdvice" pointcut="execution(* com.cql..*()) and args(name)"/>-->
        </aop:aspect>
    </aop:config>

    <bean id="aopXml" class="com.cql.aspectJ.MyAspectJXml"/>
    <bean id="orderService" class="com.cql.service.Impl.OrderService"/>
    <bean id="userService" class="com.cql.service.Impl.UserService"/>
    <bean id="meuService" class="com.cql.service.Impl.MeuService"/>
    
</beans>

7 注解配置总结

//bean添加初始化回调和销毁回调,实现方法的增强操作,在实体类中实现下面方法并使用注解
@PostConstruct
public void init(){
    System.out.println("init!!!");
}
@PreDestroy
public void destroy(){
    System.out.println("destroy!!!");
}
//设置required=false,bean中没有配置,则忽略,实现bean中引用数据类型的自动配置
①@Autowired(required = false)    
该注解用于实体类的属性字段和setter方法上,实现以注解的方式自动按【类型】注入其他bean。@Autowired添加在setter方法上,表示以setter注入,添加在构造器上,表示以构造器注入。	

②@Resource
@Resource(name = "xxx"),与@Autowired作用类似,该注解用于实体类的属性字段和setter方法上,实现以注解的方式自动按【名字】注入其他bean。“xxx”代表容器中bean的名字。若不配name属性,则在容器中寻找名为成员变量名称的bean,将其注入;若配了,选择与bean的name一致的将其注入,若没有找到,则按照类型进行匹配。


//微调基于注解的自动装配,当容器中有多个继承同一个类的参数,但类中只有一个成员变量,可以在xml中使用注解指定首要的参数
@Primary、@Qualifier
③@Primary
由于@Autowired按类型自动装配可能会导致多个【候选者】,因此通常需要对选择过程进行更多的控制。 实现这一点的一种方法是使用Spring的【@Primary 】注解。【@Primary】表示当多个bean可以作为一个依赖项的候选bean时,应该优先考虑某个特定bean。 如果在候选bean中恰好存在一个主要的bean,那么它将成为自动连接的值。

④@Qualifier
该注解有name属性,@Qualifier("xxx"),可以指定自动注入的bean的名称,通过惟一的【名称标识】选择选取一个特定的bean进行注入。
//向Spring IoC容器注册bean的注解
①    @Bean--用于在配置类中注入自定义或jar包中的对象。该注解定义在配置类中,用于指示一个方法,该方法负责【实例化、配置和初始化】一个由Spring IoC容器管理的新对象。
@Bean中有initMethod和destroyMethod属性,指定该bean的初始化回调和销毁回调的函数。

以下注解用于向容器注入自定义的对象。
②    @Component(通用注解)/@Repository(持久层)/@Service(业务层)/@Controller(控制层)
//定义一个bean的配置类
@Configuration
@ComponentScan(basePackages = "org.example")
@Import({xxx.class, xxx.class, ...})
public class AppConfig  {
}

<?xml version="1.0" encoding="UTF-8"?>
<beans 
    <context:annotation-config/>
    <bean name="appConfig" class="com.cql.AppConfig"/>
</beans>
在Spring XML文件中使用@Import元素来实现模块化配置一样,@Import注解允许一个【配置类】加载另一个【配置类】。

         如果要引入多个类,可通过以下方式,AppConfig中只需要@Import(ConfigSelector.class)即可。

public class ConfigSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com.ydlclass.A","com.ydlclass.B"};
    }
}
//定义在@Bean等注册bean的注解下,用于指定bean的作用范围
@Scope
//描述作用的注解,只起提示作用
@Description("Provides a basic example of a bean")

配置类使用配置文件的参数值

@Configuration
//读取xml
@ImportResource("classpath:/com/acme/properties-config.xml")
//读取yml和properties
@PropertySource("classpath:com/myco/app.properties")
public class AppConfig {

    @Value("${jdbc.url}")
    private String url;

    @Value("${jdbc.username}")
    private String username;

    @Value("${jdbc.password}")
    private String password;

    @Bean
    public DataSource dataSource() {
        return new DriverManagerDataSource(url, username, password);
    }
}
<beans>
    <context:property-placeholder location="classpath:/com/acme/jdbc.properties"/>
</beans>

【环境抽象】

@Profile
该注解是方法级注解,@Profile("xxx"),指定一个数据源bean所使用的参数配置

【事件监听】

@EventListener
@EventListener是方法级注解,用于事件监听

【AOP代理】

@Component
@ComponentScan(basePackages = "com.cql")
//开启AspectJ事务自动代理
@EnableAspectJAutoProxy
public class AppConfig {
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--@EnableAspectJAutoProxy注解与下面的xml配置功能一致-->
    <!-- bean definitions here -->
	<aop:aspectj-autoproxy/>
</beans>
@Aspect    //定义一个切面类
@Component
public class MyAspectJAnno {
    /**
     * 声明一个切点,pointCut()指向execution中定义的com.cql类下的所有public方法
     */
    @Pointcut("execution(public * com.cql..*(..))")
    private void pointCut(){
    }

    /**
     * 让代理对象实现新的接口,该接口的方法会在最后自动执行
     */
    @DeclareParents(value="com.cql.service.Impl.OrderService",defaultImpl= MeuService.class)
    public static IMeuService meuServiceWay;

    @Before("pointCut()")
    private void beforeAdvice(JoinPoint jp){
    }

    @AfterThrowing(value = "execution(public * com.cql..*(..))", throwing="ex")
    public void afterThrowingAdvice(ArithmeticException ex) {
    }

    @AfterReturning("pointCut()")
    private void afterReturningAdvice(){
    }
    @After("pointCut()")
    private void afterAdvice(){
    }

    /**
     * around可用于事务的增强
     * @param pjp
     * @return
     */
    @Around("pointCut()")
    private Object aroundAdvice(ProceedingJoinPoint pjp){
	}
}

【事务】

@Transactional
public void transferMoney1(String from, String to, Integer money) {
    // 转账其实是两个语句
    String moneyFrom = "update spring_tx set salary = salary - ? where name = ? ";
    String moneyTo = "update spring_tx set salary = salary + ? where name = ? ";
    // 从转账的人处扣钱
    jdbcTemplate.update(moneyFrom, money, from);
    int i =1/0;
    jdbcTemplate.update(moneyTo, money, to);
}

<!--在xml中开启事务注解-->
<tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>

【纯注解事务】

@Configuration
@ComponentScan(basePackages = "com.cql")
@EnableTransactionManagement //开启事务
@PropertySource("classpath:jdbc.properties")
public class AppConfig {

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值