Spring usage details
IOC container
/** * Get the Ioc core container of spring and get the object according to the id * * ApplicationContext Three common implementation classes: * ClassPathXmlApplicationContext: He can load the configuration file under the classpath. It is required that the configuration file must be under the classpath. It can't be loaded without you. (more commonly used) * FileSystemXmlApplicationContext: He can access the configuration file in any path on the disk (he must have access) * * * AnnotationConfigApplicationContext: It is used to read annotations and create containers * Problems caused by two interfaces of the core container * ApplicationContext:(Singleton object) adopts this interface * When he builds the core container, the strategist who creates the object adopts the method of immediate loading. That is, once you play with the configuration file, you will immediately create the objects in the configuration file * BeanFactory:((multiple objects) * When he builds the core container, the strategy of creating objects is to delay loading. That is, when the object is obtained according to the id and when the object is actually created * @param args */ public static void main(String[] args) { //1. Get the core container object ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); //2. Get the bean object according to the id IAccountService as = (IAccountService) ac.getBean("accountService"); IAccountDao adao =ac.getBean("accountDao",IAccountDao.class); System.out.println(as); System.out.println(adao); as.saveAccount(); //----------beanFactory---------\ /*Resource resource= new ClassPathResource("bean.xml"); BeanFactory factory= new XmlBeanFactory(resource); IAccountDao adao =factory.getBean("accountDao",IAccountDao.class);*/ }
Bean
<!--Leave the creation of objects to spring To manage--> <!--spring yes bean Management details 1.establish bean Three ways of 2.bean Scope of object 3.bean Object lifecycle --> <!--establish bean Three ways of--> <!--**The first way: use the default constructor to create** stay spring Used in the configuration file bean Label with id and class Property, and there are no other properties and labels. The default constructor is used bean Object. At this time, if there is no default constructor in the class, the object cannot be created <bean id="accountService" class ="service.impl.AccountServiceImpl"></bean> --> <!--**The second method: create objects using methods in a common factory (create objects using methods in a class and store them in spring (container)** <bean id="instanceFactory" class ="factory.instanceFactory"></bean> <bean id="accountService" factory-bean="instanceFactory" factory-method="getAccountService"></bean> --> <!--The third way: use**Creating objects using static methods in a static factory**(Use static methods in a class to create objects and store them in spring (container) <bean id="accountService" class="factory.staticFactory" factory-method="getAccountService"></bean> --> <!--bean Scope adjustment of bean Tagged scope attribute Function: used to formulate bean Scope of action Value **singleton Singleton (default) prototype Multiple cases request act on web Application request scope session act on web Application session scope** global-session The session scope (global session scope) that acts on the cluster environment. When it is not a cluster environment, it is session <bean id="accountService" class ="service.impl.AccountServiceImpl" scope="singleton"></bean> --> <!--bean Object lifecycle Singleton object Birth: the object is born when the container is created Live; As long as the container remains, the object remains alive Death: the container destroys and the object dies Summary: the life cycle of a single case is the same as that of a container Multi instance object Birth: when we use objects spring Create objects for us Alive: an object is alive as long as it is in use. Death: when an object is not used for a long time and there is no other object reference, the Java Garbage collector collection --> <bean id="accountService" class="service.impl.AccountServiceImpl" scope="prototype" init-method="init" destroy-method="destroy"> </bean>
Dependency injection
<!--spring Dependency injection in Dependency injection: Dependency Injection IOC Role of: Reduce coupling (dependencies) between programs Dependency management: I'll give it to you later spring To maintain Objects of other classes need to be used in the current class spring To provide for us, we only need to specify in the configuration file Dependency maintenance: It is called dependency injection. Dependency injection: Data that can be injected: Basic types and String other bean Type (configured in configuration file or annotation) bean) Complex type/Collection type There are three injection methods **1.Use constructor to provide 2.use set Method provision 3.Use annotation to provide** --> <!--Constructor Inject Labels used: constructor-arg Where the label appears: bean Inside of label Attributes in Tags type:It is used to specify the data type of the data to be injected, which is also the type of one or some parameters in the earlier function. index: Used to specify the data to be injected and assign a value to the parameter specifying the index position in the constructor. The position of the parameter index starts at 0 name: Used to assign a value to the parameter with the specified name in the constructor Commonly used ===========The above three are used to assign a value to which parameter in the constructor=========== value: Used to provide basic types and String Type of data ref: Used to specify other bean Type data. He means in spring of IOC In the core container bean object Advantages: In getting bean When injecting data into an object, operations must be performed. Otherwise, the object cannot be created successfully Disadvantages: Changed bean The instantiation method of objects makes it necessary to provide these data when creating objects --> <bean id="accountService" class="service.impl.AccountServiceImpl"> <constructor-arg name="name" value="test111"></constructor-arg> <constructor-arg name="age" value="18"></constructor-arg> <constructor-arg name="birthday" ref="now"></constructor-arg> </bean> <!--Configure a date object--> <bean id="now" class="java.util.Date"></bean> <!--set Method injection More common way Labels involved: property Location of occurrence: bean Inside of label Label properties name: Used to specify the method to call when injecting set Method name value: Used to provide basic types and String Type of data ref: Used to specify other bean Type data. He means in spring of IOC In the core container bean object Advantages: There are no explicit restrictions when creating objects. You can directly use the default constructor Disadvantages: If a member must have a value, it is possible to get the object set Method not executed --> <bean id="accountService2" class="service.impl.AccountServiceImpl2"> <property name="name" value="TEst"></property> <property name="age" value="18"></property> <property name="birthday" ref="now"></property> </bean>
<!-- The following two can be passed directly Component/Service/Repostory/Controller + AutoWired realization --> <!--to configure Service object--> <bean id="accountService" class="com.lxc.service.impl.AccountServiceImpl"> <!--injection dao--> <property name="accountDao" ref="accountDao"></property> </bean> <!--to configure Dao object--> <bean id="accountDao" class="com.lxc.dao.impl.AccountDaoImpl"> <!--injection QueryRunner--> <property name="runner" ref="runner"></property> </bean> <bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype"> <!--Injection data source--> <constructor-arg name="ds" ref="dataSource"></constructor-arg> </bean> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <!--Necessary information for connecting to the database--> <property name="driverClass" value="com.mysql.jdbc.Driver"></property> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/eesy"></property> <property name="user" value="root"></property> <property name="password" value="11111111"></property> </bean>
@Autowired private IAccountService accountService;
AOP
Dynamic agent
final Producer producer = new Producer(); /** * Dynamic agent * Features: bytecode can be created with use and loaded with use * Function: on the basis of not modifying the source code, the other party can enhance it * Classification: * Interface based dynamic agent * Subclass based dynamic agent * Interface based dynamic proxy: * Class involved: Proxy * Provider: JDK official * How to create a proxy object: * Use the newProxyInstance method in the Proxy class * Requirements for creating proxy objects * The proxy class implements at least one interface. If it does not, it cannot be used * newProxyInstance Method parameters * ClassLoader: Class loader * It is used to load the bytecode of the proxy object and uses the same class loader as the proxy object. Fixed writing * Class[]: Bytecode array * It is used to make the proxy object and the proxied object have the same method. Fixed writing * InvocationHandler: Code to provide enhancements * He asked us to write how to act as an agent. We usually write an implementation class of the interface. Usually, it is an anonymous internal class, but it is not necessary * Who writes the implementation classes of this interface * * */ IProducer proxyProducer = (IProducer) Proxy.newProxyInstance(producer.getClass().getClassLoader(), producer.getClass().getInterfaces(), new InvocationHandler() { /** * Function: * * any interface method of any proxy object that executes the proxy object will pass through this method** * @param proxy : Reference to proxy object * @param method : Currently executed method * @param args: Parameters required for the current execution method * @return : Has the same method value as the proxied object * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //Provide enhanced code Object returnValue = null; //1. Gets the execution parameters of the method float money =(float) args[0]; //Determine whether the current method is sales if("saleProduct".equals(method.getName())){ returnValue=method.invoke(producer,money*0.8f); } return returnValue; } }); proxyProducer.saleProduct(10000f);
Implementation of AOP based on dynamic agent
public class BeanFactory { private TransactionManager txManager; public void setTxManager(TransactionManager txManager) { this.txManager = txManager; } private IAccountService accountService; public final void setAccountService(IAccountService accountService) { this.accountService = accountService; } /** * Gets the proxy object of the service * @return */ public IAccountService getAccountService(){ return (IAccountService) Proxy.newProxyInstance(accountService.getClass().getClassLoader(), accountService.getClass().getInterfaces(), new InvocationHandler() { /** * Add transaction support * @param proxy * @param method * @param args * @return * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object rtValue=null; try { //1. Open transaction txManager.beginTransaction(); //2. Perform operation rtValue = method.invoke(accountService,args); //3. Commit transaction txManager.commit(); //4. Return results return rtValue; } catch (Exception e) { //5. Rollback operation txManager.rollback(); throw new RuntimeException(e); } finally { //6. Release connection txManager.release(); } } }); } }
Through the dynamic proxy, the incoming class loader, the interface it implements, and an enhanced method (we need to implement it)
This method is how to enhance the proxy class
In this example, it is written that each method in the accountService class has been enhanced to realize transaction control. Originally, each method in the accountService class needs to write such a lengthy control transaction, but now we can call all methods in the original accountService class through the proxy object of the accountService class, No matter what method is called, it will start with the invoke function when it is executed to mathod Only when you invoke (...) will you really call the code in accountService. Therefore, we have enhanced all methods in accountService and realized transaction control.
With this proxy object, we can replace the original accountService class with this proxy object and use the static factory method to create this proxy object
<bean id="proxyAccountService" factory-bean="beanFactory" factory-method="getAccountService"></bean>
However, it is cumbersome to write this. We need to configure the dynamic proxy ourselves. If there are many objects that need proxy, it will be more troublesome. So there is AOP
AOP concept
- Joinpoint:
- Connection points refer to those intercepted points, and Spring refers to methods. I understand that all methods in our accountService interface are not just enhanced methods.
- Pointcut
- The pointcut is the definition of which joinpoints we want to intercept, which refers to the enhanced methods in accountService.
- Advice:
- Notification refers to what needs to be done after intercepting the Joinpoint. It refers to what needs to be done before and after the enhanced code intercepts the invoke
- Notification includes pre notification, post notification, one field notification, final notification, and surround notification (with obvious pointcut method calls)
- Introduction
- Target:
- The target object of the proxy is the object to be proxied. Here is accountService
- Weaving:
- Refers to the process of applying enhancements to the target object to create a new proxy object
- The process of adding transaction support is weaving
- Proxy:
- After a class is woven and enhanced by AOP, a result proxy class is generated
- It's a dynamic proxy. The object return ed is a proxy
- Aspect:
- It's a combination of pointcuts and notifications
- The process of configuring how to enhance pointcut methods is faceting
AOP configuration
Configuration based
,<!--spring Medium based XML of AOP Configuration steps 1,Notify Bean Give it to me, too spring To manage 2,use aop:config Label indicates start AOP Configuration of 3,use aop:aspect The label indicates the start of the configuration section id attribute:Is to provide a unique identification for the section ref attribute:Is the specified notification class bean of id 4,stay aop:aspect The internal of the tag uses the corresponding tag to configure the type of notification Our example now is to let printLog Method executes before the pointcut method executes: so it's a pre notification aop:before: Indicates pre notification method Properties: used to specify Logger Which method in the class is pre notification pointcut Attribute: used to specify the pointcut expression. The meaning of the expression refers to which methods in the business layer are enhanced How to write the pointcut expression: keyword: execution expression: Access modifier: return value package name.Package name.Package name...Class name.Method name (parameter list) Standard expression: public void com.lxc.service.impl.AccountServiceImpl.saveAccount() The access modifier can be omitted void com.lxc.service.impl.AccountServiceImpl.saveAccount() The return value can use wildcards to represent any return value * com.lxc.service.impl.AccountServiceImpl.saveAccount() The package name can use wildcards to represent any package. But there are several levels of packages, you need to write several*. * *.*.*.*.AccountServiceImpl.saveAccount() Package name can be used..Represents the current package and its sub packages * *..AccountServiceImpl.saveAccount() Both class and method names can be used*To achieve general distribution * *..*.*() Parameter list: You can write data types directly: Basic type direct write name int Reference type write package name.Method of class name java.lang.String Wildcards can be used*Represents any type, but must have parameters have access to..It indicates whether there are parameters or not. Parameters can be of any type All pass configuration: * *..*.*(..) The common writing method of pointcut expression in actual development: Switch to all methods under the business layer implementation class * com.lxc.service.impl.*.*(..) --> <!--to configure logger class--> <bean id="logger" class="com.lxc.utils.Logger"></bean> <!--to configure AOP--> <aop:config> <aop:aspect id="logAdvice" ref="logger"> <!--Configure the type of notification and establish the association between notification methods and pointcut methods--> <aop:before method="printLog" pointcut="execution(* com.lxc.service.impl.*.*(..)))"></aop:before> </aop:aspect> </aop:config>
Type of configuration
<!--to configure logger class--> <bean id="logger" class="com.lxc.utils.Logger"></bean> <!--to configure AOP--> <aop:config> <!--Configure pointcut expressions id Property specifies the unique identity of the expression. expression Property specifies the content of the expression This label is written in aop:aspect The inside of the label can only be used in the current section It can also be written in aop:aspect Outside, all sections are available at this time --> <aop:pointcut id="pt1" expression="execution(* com.lxc.service.impl.*.*(..))"></aop:pointcut> <!--Configure section--> <aop:aspect id="logAdvice" ref="logger"> <!--Configure the pre notification, which is executed before the pointcut method is executed <aop:before method="beforePrintLog" pointcut-ref="pt1"></aop:before>--> <!--Configure the post notification to execute after the normal execution of the pointcut method. He and exception notification can always execute only one <aop:after-returning method="afterReturningPrintLog" pointcut-ref="pt1"></aop:after-returning>--> <!--Configure exception notification. Only one exception and post notification can be executed after the execution of pointcut method generates an exception <aop:after-throwing method="afterThrowingPrintLog" pointcut-ref="pt1"></aop:after-throwing>--> <!--Configure the final notification to be executed after it, regardless of whether its pointcut method is executed normally <aop:after method="afterPrintLog" pointcut-ref="pt1"></aop:after>--> <!--For details on configuring surround notifications, see Logger In class--> <aop:around method="aroundPrintLog" pointcut-ref="pt1"></aop:around> </aop:aspect> </aop:config>
The method here is how to enhance the method, not the pointcut method
/** * Around Advice * Question: * When we configure the wrap notification, the pointcut method is not executed, and the notification method is executed * analysis: * By comparing the surround notification code in the dynamic agent, it is found that the surround notification of the dynamic agent has a clear entry point method call, but not in our code. * solve: * spring The framework provides us with an interface: proceeding joinpoint. The interface has a method, procedure (), which is equivalent to explicitly calling the pointcut method. * The interface can be used as a method parameter around the notification. During program execution, the spring framework will provide us with the implementation class of the interface for us to use * spring Surround notifications in: * It is a way for us to manually control when the enhanced method is executed in the code provided by the spring framework */ public Object aroundPrintLog(ProceedingJoinPoint pjp){ Object rtValue=null; try { Object[] args=pjp.getArgs(); System.out.println("Advance notice: Logger Quasi heavy aroundPrintLog Method starts logging"); rtValue=pjp.proceed(args);//Explicitly invoke business layer methods (pointcut methods) System.out.println("Post notification: Logger Quasi heavy aroundPrintLog Method starts logging"); return rtValue; }catch (Throwable t){ System.out.println("Exception notification: Logger Quasi heavy aroundPrintLog Method starts logging"); throw new RuntimeException(t); }finally { System.out.println("Final notice: Logger Quasi heavy aroundPrintLog Method starts logging"); } }
Annotation based
<!--to configure spring Open annotation AOP Support of--> <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
@Component("logger") @Aspect//Indicates that the current class is a facet type public class Logger { @Pointcut("execution(* com.lxc.service.impl.*.*(..))") private void pt1(){} /** * Before advice */ @Before("pt1()") public void beforePrintLog() { System.out.println("Advance notice: Logger Class beforePrintLog Method starts logging"); } }
Write your own classes to enhance the pointcut and realize transaction control
Transaction control should be in the business layer
<!--to configure aop--> <aop:config> <!--Configure common pointcut expressions--> <!--Which method of which class do you want to enhance--> <aop:pointcut id="pt1" expression="execution(* com.lxc.service.impl.*.*(..))"/> <aop:aspect id="txAdvice" ref="txManager"> <!--Configure pre notification and start transaction--> <aop:before method="beginTransaction" pointcut-ref="pt1"></aop:before> <!--Configure post notification to commit transactions--> <aop:after-returning method="commit" pointcut-ref="pt1"></aop:after-returning> <!--Configure exception notification and roll back transactions--> <aop:after-throwing method="rollback" pointcut-ref="pt1"></aop:after-throwing> <!--Configure the final notification to release the connection--> <aop:after method="release" pointcut-ref="pt1"></aop:after> </aop:aspect> </aop:config>
Spring support for transactions
Configuration based
<!--Configure transaction manager--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!--Configure notifications for transactions--> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <!--Configure the properties of the transaction isolation="" Used to specify the isolation level of transactions. The default is DEFAULT,Indicates that the default isolation level of the database is used no-rollback-for="" Used to specify an exception. When this exception occurs, the transaction will not roll. When other exceptions occur, the transaction will roll back. There is no default value. Indicates that any exceptions are rolled back propagation="" Used to specify the propagation behavior of transactions. The default value is REQUIRED,It means that there will be transactions, adding, deleting and modifying options. The query method can be selected SUPPORTS. read-only="" Specifies whether the transaction is read-only. Only query methods can be set to true. The default value is false,Indicates reading and writing rollback-for="" Used to specify an exception. When the exception is generated, the transaction will be rolled back. When other exceptions are generated, the transaction will not be rolled back. There is no default value. Indicates that any exceptions are rolled back timeout="" Used to specify the timeout of a transaction. The default value is-1,Indicates no timeout. If a value is specified, it is in seconds. --> <tx:attributes> <tx:method name="*" propagation="REQUIRED"/> <tx:method name="find*" propagation="SUPPORTS" read-only="true"></tx:method> </tx:attributes> </tx:advice> <!--to configure aop--> <aop:config> <aop:pointcut id="pt1" expression="execution(* com.lxc.service.impl.*.*(..))"/> <!--Establish the corresponding relationship between pointcut expression and transaction notification--> <aop:advisor advice-ref="txAdvice" pointcut-ref="pt1"></aop:advisor> </aop:config>
Annotation based
<!-- spring Annotation based declarative transaction control configuration steps in 1,Configure transaction manager 2,open spring Support for annotation transactions 3,Where transaction support is needed, there are@Transactional annotation --> <!--Configure transaction manager--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!--open spring Support for annotation transactions--> <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
@Transactional(propagation = Propagation.REQUIRED,readOnly = false) @Override public void transfer(String sourceName, String targetName, Float money) { }